syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

Visual C++ 2010 SP1でのMFC拡張

(これは2011-05-27に書いた故OCNブログの記事を移植したものです)

Microsoftが.NETに注力を始めてからずいぶんと影が薄くなったのが、Visual C++向けのWin32 APIラッパー/デスクトップアプリケーションフレームワークであるMFCなんですが、VC 2010になっても結局MFCはひっそりと拡張され続けています。2010ではリボン リソース エディター(リボン デザイナー)などの目玉機能が追加された挙げ句、SP1では下記2つのコア機能が追加になっています。

あまり話題にはなっていないけど、WPFをどうしても採用できない案件で、高速かつリッチなUIをネイティブ実装するのに使えそうです。どのみちコードベースでガリガリ書いていく必要があるので、生産性や保守性の観点からはWPFには遠く及ばないんですが、D2D/WAMはCOMゆえに結構面倒な部分があるので(COMを知らない人には使えない、また知っていてもコールバック*1まわりが面倒)、そのラッパーが用意されているのは助かるかもしれません。

D2Dが使えるのはWindows 7/Vista SP2 + Platform Update以降であり、Windows XPではD2Dがサポートされないので当然ハードウェア アクセラレーションが効かないのはともかくとして、多分WAMラッパーのほうもXPでは機能制限があるようです。というかD2D/WAMはXPにはバックポートされていないので多分ラッパーも使えません。
WPFは豊富なアニメーション機能が便利なんですが、そのフレームワークのみをネイティブCOM実装したのがWAMになります。とはいえXAML連携などはできません。

Visual Studio 2010 SP1 用の MFC の追加
https://msdn.microsoft.com/ja-jp/library/gg482719.aspx

チュートリアル: MFC プロジェクトへの D2D オブジェクトの追加
https://msdn.microsoft.com/ja-jp/library/gg482848.aspx

チュートリアル: MFC プロジェクトへのアニメーションの追加
https://msdn.microsoft.com/ja-jp/library/gg466500.aspx

VS 2010 SP1をインストールすると、下記の場所にサンプル コードのアーカイブがインストールされます。ただし中に入っているのは差分サンプルが少しだけです。
%ProgramFiles(x86)%\Microsoft Visual Studio 10.0\Samples\1041\VC2010SP1Samples.zip

MFCソースコードが付属しているし、マニュアルもそれなりにあるので、ヘビーユーザーであれば使い方は自分で調べればよいのですが、もっと有用な実装サンプルが増えないと、初心者には厳しいかもしれません。
また、MFC用に提供されているDirect2Dラッパーは、Direct2D 1.0専用になります。Windows 8に実装されているDirect2D 1.1や、Windows 8.1に実装されているDirect2D 1.2を使いたい場合は、MFCラッパーではなく直接COM APIを操作する必要があります。


しかし結局COMはいつまでも残り続けるしぶとい技術ですね。DCOMはWCFなどによってほぼ完全に置換されましたが、COMはネイティブC++から利用できるソフトウェアコンポーネント再利用技術として、今後もしばらくMSプラットフォームの中核であり続けるでしょう。実はWindows 8.xのWinRTもCOMの拡張技術だったりします。

*1:COMのコールバックはイベントシンクという仕組みを使います。イベントシンクはプロセス透過でDCOMにも使える反面、登録作業がかなり煩雑です。

GDI+でアンチエイリアスEMFを作成

(これは2012-09-08に書いた故OCNブログの記事を移植したものです)

MFCCMetaFileDCWindows拡張メタファイル(EMF)を作成した場合、たとえGdiplus::Graphics::FromHDC()でバインドしたGDI+グラフィックスを使ってそのメタファイルを描画してもアンチエイリアスがかかりません。

アンチエイリアスのかかったWindows拡張メタファイル(EMF+)を作りたい場合、Gdiplus::Metafileを使う必要があります。Gdiplus::EmfTypeEmfPlusOnlyもしくはGdiplus::EmfTypeEmfPlusDualオプションを付けてストリーム上に作成したMetafileに、Graphics::FromImage()でバインドしたGDI+グラフィックスを使って描画すればOK。Metafileコンストラクタの第1引数にはファイルパス文字列のほかにCOMのIStreamを渡せるオーバーロードがあるので、ファイルストリーム上だけでなくメモリーストリーム上にメタファイルを作成することもできます。

なお、Graphics::EnumerateMetafile()を使うことで、アンチエイリアスのかかっていないEMFファイルを開き、アンチエイリアスのかかったEMF+ファイルに変換して書き出す、ということもできます。

「EnumerateMetafile()を使ってEMFをEMF+に変換するにはどうすればいいの?」という質問をいただいたので、参考までに簡単なサンプルを下記にアップロードしておきました。ただし、色の半透明化として使われているタイル パターン ブラシまわりなど、対応が不十分だったり、完全に未対応だったりするEMRコマンドがたくさんあります。ソースコードの2次利用はご自由に、ただし自己責任でどうぞ。

MetafileConvertTest.zip

なお、EnumerateMetafile()で列挙されるレコード(コマンド+付随データ)をそのままMetafile::PlayRecord()に渡しても、アンチエイリアスの効いたEMF+(GDI+コマンド)に自動変換してくれるようなことはありません。EMRレコードの意味的な解析が必要になります。また、EMRコマンド構造体が必要になるので、.NETよりネイティブC++のほうが変換処理を書きやすいはずです。変換プログラムとしては、コマンドラインのフリーウェア「EMF to EMF+ Converter」がありますが、こちらはソースコードが公開されてないようです。ちなみにGDIのコマンドと従来のEMFファイルのコマンドは1対1で対応するため、EMFファイルからGDIコマンドを復元するのは容易ですが、GDI+のDrawRectangle()やDrawEllipse()で描画した図形を、従来のEMF Onlyメタファイル形式で保存すると、PolygonやBezierで記録されてしまいます(1対1で対応しない、つまり情報が欠落してしまう不可逆変換)。なので、EMF OnlyのGDIコマンドを、GDI+のDrawPolygon()やDrawBeziers()で変換すること自体はできますが、元となる描画に使用されたGDI+コマンドを復元するのは困難となります。個人的には、EMFからEMF+に変換するよりは、メタファイル生成プログラムを書き直して最初からEMF+として出力するように修正することをお勧めします。

■ EMF+ (オリジナル)
https://sygh-jp.github.io/content_hosting/my_program_ss/emf_plus_test.png

■ EMF (ダウンコンバート、アンチエイリアスの欠落と半透明効果のタイル化)
https://sygh-jp.github.io/content_hosting/my_program_ss/emf_only_test.png

■ EMF+ (アップコンバート、ただし半透明効果の復元には未対応)
https://sygh-jp.github.io/content_hosting/my_program_ss/emf_plus_convert_output_test.png

ネイティブXPSドキュメントAPIが使えるWindows 7(とVista SP2 + Platform Update)以降では、メタファイルの存在意義が小さくなりつつありますし、WPFではWindowsメタファイル形式がそもそもサポートされていません。が、WordやExcelに直接貼り付けられるEMFは、Windows上でのベクトル画像フォーマットとしてまだ利用価値がありそうです。

ちなみにWin7からVistaにPlatform Updateの形でバックポートされたネイティブAPIは、XPSのほかにもかなりたくさんあります。自分が知っている範囲でも、リボン フレームワーク、Direct2D/DirectWrite、DirectX 11、Windows Animation Manager (WAM)、など。全部COMです。WAMはゲーム開発にも使えそうです。

Windows 8(とWin7 SP1 + Platform Update)以降に搭載されている新しいDirect2D 1.1は、印刷処理やメタファイルへの出力もサポートするらしいんですが、メタファイルってのはどういうフォーマットになるんでしょうか? EMF+をサポートするわけじゃないと思うけど……やっぱりXPSなんでしょうか? いずれ試してみたいと思います。

Visual Studioの読み取り専用ファイル編集確認ダイアログ

(これは2013-05-11に書いた故OCNブログの記事を移植したものです)

Visual Studioで読み取り専用ファイルを編集しようとしたら、「読み取り専用ファイルを編集」というタイトルで、「編集しようとしたファイル XXX はディスクで読み取り専用です。ファイルを書き込み可能にしますか? それともこのまま編集しますか?」という確認ダイアログが出てきて、「書き込み可能に設定」をクリックすると読み取り専用属性が自動解除されて編集を開始できるんですが、「今後このダイアログ ボックスを表示しない(メモリでの編集を許可しない)」というチェックボックスを誤ってONにして閉じてしまったら、ダイアログが二度と出てこなくなってしまった。

https://sygh-jp.github.io/content_hosting/software_ss/vs_readonly_file_edit_confirm_dialog_2013_05_11b.png

「ツール」→「オプション」→「環境」→「ドキュメント」あたりにダイアログの表示を復活させるオプションがあるんじゃないかと思って探しましたが、VS 2012ではどこにも見あたらない。

ネット検索をかけてみても、MSDNに「編集しようとしたファイル <name> はディスクで読み取り専用です。」というページはあるんですが、「ソース管理のためのプラグイン タブ ([オプション] ダイアログ ボックス)」で説明されている[リセット]ボタンとやらがどこにも存在しない。ヘルプはVS 2008のものらしいので、VS 2008はどうなってるのか調べたところ、やはりVS 2008にも該当するボタンなどは見あたらない。

このダイアログが出てこないと、読み取り専用ファイルの属性をIDEで自動解除させることができなくなってしまい不便なので、仕方なく「ツール」→「オプション」→「環境」→「ドキュメント」の、「読み取り専用ファイルの編集を有効にし、保存時に警告する」という項目をONにして対処することに。

https://sygh-jp.github.io/content_hosting/software_ss/vs_readonly_file_save_confirm_dialog_2013_05_11b.png

ただ、このオプションだと、「読み取り専用ファイルの保存前に」確認ダイアログが出るだけで、「読み取り専用ファイルの編集開始時に」確認ダイアログは出ません。自分としては「編集開始時に」確認ダイアログが出てくれたほうがありがたいんですが……誰かダイアログ表示の復活方法、知りませんか?

※2016-06-26追記:
コメントで提供していただいたヒントをもとに調べたところ、やはりレジストリに当該フラグ(の否定値)が保存されているようです。新規セットアップしたWindows 8.1上にて、Visual Studio 2012(11.0)/2013(12.0)/2015(14.0) のレジストリ情報を調べてみたところ、下記の値がすべて1になっていました。もし当該ダイアログを誤って非表示にしてしまった場合、下記を0から1に戻すことで対処できるものと思われます(当然レジストリの編集は自己責任で)。

  • HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\SourceControl\AllowUncontrolledInMemoryEditing
  • HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\SourceControl\AllowUncontrolledInMemoryEditing
  • HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0\SourceControl\AllowUncontrolledInMemoryEditing

個人的には、ダイアログに「今後このダイアログを表示させない」チェックボックスを表示するんだったら、ダイアログ表示を再び復活させるオプションをちゃんと分かりやすいところに配置するべきだと思います。さらにそういうのが複数あるんだったら、リスト形式で一元管理できるべきなんですが……(コードエディターでの文字列検索/置換終了後に出てくる確認ダイアログの抑制に関しては、復活オプションが存在しますが、1つのチェックボックスで複数のオプションフラグがまとめて管理されてしまっています)

ショートカットファイル(.lnk)をC#で読込・解析・編集・作成

Windows 8.1用にHDDを移行したとき、昔使っていた古いドライブレターをいくつか廃止して統合したので、参考資料画像群*1のしおりとして残しておいたショートカットファイル(*.lnk)のリンク切れが大量に発生しました(リンク先の実体ファイルは別ドライブの別ディレクトリに移動したため)。今日はこいつらをなんとかしてみます。
Windowsのショートカットファイルはバイナリ形式なので、リンク先などの中身を解析・編集するには、情報操作をするためのShell APIを使ったプログラムを書く必要があるのですが、今回はC#での一括処理を書いてみました*2

ShortcutConverter.zip

参照設定に「Windows Script Host Object Model」アセンブリを追加しています。

といっても、ただショートカットファイルのターゲットパスをC#コードで置換するだけでは芸がないし応用も効かないので、

  1. まず古いショートカットファイルの内部情報を中間XMLとして書き出す(Lnk2Xml)
  2. パスの置換・正常化はテキストエディターで中間XMLに対して行なう
  3. 編集後の中間XMLから新たにショートカットファイルを生成する(Xml2Lnk)

という柔軟な多段処理を行なえるようにモジュールを分割します。
以下、処理の抜粋。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyShellHelpers
{
  public static class ShellShortcutHelper
  {
    public static void XmlToLnk(string strInListXmlFilePath)
    {
      var shell = new IWshRuntimeLibrary.WshShell();

      using (var stream = new System.IO.FileStream(strInListXmlFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
      {
        // LINQ to XML (for XPath) を使って読み出す。

        var xDoc = System.Xml.Linq.XDocument.Load(stream);

        var rootNode = xDoc.Root;

        var query =
          from node in rootNode.Elements("Shortcut")
          select node;

        foreach (var elem in query)
        {
          var nonameData = new
          {
            ShortcutFilePath = elem.Attribute("ShortcutFilePath"),
            TargetPath = elem.Attribute("TargetPath"),
            Arguments = elem.Attribute("Arguments"),
            WorkingDirectory = elem.Attribute("WorkingDirectory"),
            Hotkey = elem.Attribute("Hotkey"),
            WindowStyle = elem.Attribute("WindowStyle"),
            Description = elem.Attribute("Description"),
            IconLocation = elem.Attribute("IconLocation"),
          };

          System.Diagnostics.Debug.Assert(nonameData.ShortcutFilePath != null);
          var objShortcut = shell.CreateShortcut(nonameData.ShortcutFilePath.Value) as IWshRuntimeLibrary.IWshShortcut;

          System.Diagnostics.Debug.Assert(nonameData.TargetPath != null);
          objShortcut.TargetPath = nonameData.TargetPath.Value;

          System.Diagnostics.Debug.Assert(nonameData.Arguments != null);
          objShortcut.Arguments = nonameData.Arguments.Value;

          System.Diagnostics.Debug.Assert(nonameData.WorkingDirectory != null);
          objShortcut.WorkingDirectory = nonameData.WorkingDirectory.Value;

          System.Diagnostics.Debug.Assert(nonameData.Hotkey != null);
          objShortcut.Hotkey = nonameData.Hotkey.Value;

          System.Diagnostics.Debug.Assert(nonameData.WindowStyle != null);
          // 1:通常、3:最大化、7:最小化。
          // http://msdn.microsoft.com/ja-jp/library/cc364498.aspx
          objShortcut.WindowStyle = Int32.Parse(nonameData.WindowStyle.Value);

          System.Diagnostics.Debug.Assert(nonameData.Description != null);
          objShortcut.Description = nonameData.Description.Value;

          System.Diagnostics.Debug.Assert(nonameData.IconLocation != null);
          objShortcut.IconLocation = nonameData.IconLocation.Value;

          // IWshShortcut.Save() メソッドを呼び出すと、設定されたプロパティにしたがってショートカット ファイルを保存する。
          // 逆に言えば Save() を実行するまではストレージに保存されない。
          objShortcut.Save();
        }
      }
    }

    public static void LnkToXml(IEnumerable<string> inShortcutFilePaths, string strOutListXmlFilePath)
    {
      var shell = new IWshRuntimeLibrary.WshShell();

      var xmlSettings = new System.Xml.XmlWriterSettings();
      xmlSettings.Indent = true;
      xmlSettings.IndentChars = "\t";
      xmlSettings.Encoding = new UTF8Encoding();

      using (var stream = new System.IO.FileStream(strOutListXmlFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write))
      {
        using (var xmlWriter = System.Xml.XmlWriter.Create(stream, xmlSettings))
        {
          // 書き込みにも LINQ to XML を使えるが、今回はオーソドックスな方法を使う。

          xmlWriter.WriteStartDocument();
          xmlWriter.WriteStartElement("Shortcuts");
          foreach (var path in inShortcutFilePaths)
          {
            System.Diagnostics.Debug.Assert(System.IO.File.Exists(path));

            // WshShell.CreateShortcut() で既存のショートカット ファイルを開くこともできる。
            var objShortcut = shell.CreateShortcut(path) as IWshRuntimeLibrary.IWshShortcut;

            xmlWriter.WriteStartElement("Shortcut");

            xmlWriter.WriteStartAttribute("ShortcutFilePath");
            xmlWriter.WriteString(path);
            xmlWriter.WriteEndAttribute();

            // NOTE: 64bit OS 上で 32bit アプリケーションから IWshShortcut を使用すると、
            // もとのショートカット ファイルの [リンク先] に "C:\Program Files\..." と記載されてあっても、
            // TargetPath が "C:\Program Files (x86)\..." に勝手に置き換わってしまう模様。
            // 逆に最初から "C:\Program Files (x86)\..." と記載されているものに関しては、
            // 64bit アプリケーションで実行してもそのままとなる。
            // 結論としては、64bit OS でショートカットを読み出し・作成する場合、必ず 64bit ネイティブ プロセスで処理を実行すること。

            //string strTargetPath = objShortcut.TargetPath;

            xmlWriter.WriteStartAttribute("TargetPath");
            xmlWriter.WriteString(objShortcut.TargetPath);
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteStartAttribute("Arguments");
            xmlWriter.WriteString(objShortcut.Arguments);
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteStartAttribute("WorkingDirectory");
            xmlWriter.WriteString(objShortcut.WorkingDirectory);
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteStartAttribute("Hotkey");
            xmlWriter.WriteString(objShortcut.Hotkey);
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteStartAttribute("WindowStyle");
            xmlWriter.WriteString(objShortcut.WindowStyle.ToString());
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteStartAttribute("Description");
            xmlWriter.WriteString(objShortcut.Description);
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteStartAttribute("IconLocation");
            xmlWriter.WriteString(objShortcut.IconLocation);
            xmlWriter.WriteEndAttribute();

            xmlWriter.WriteEndElement();
          }
          xmlWriter.WriteEndElement();
          xmlWriter.WriteEndDocument();
        }
      }
    }
  }
}

困ったことがあったらすぐに自動化ツールをさらっと書けるのがプログラマーの特権ですね。

XmlToLnk()は匿名型やLINQ to XMLを使うなど、やや技巧的に書いています。
なお、ショートカットファイルを読み込むときの注意点はLnkToXml()内のコメントに記載しています。Visual C#を使うときは、プロジェクト設定で[32 ビットの優先]というチェックボックスを外しておきましょう。

*1:実はいかがわしい画像が大半だということはみんなにはナイショだよ。

*2:VBScriptJScriptVB.NETVC++でもやろうと思えばできると思いますが、自分は現時点で最強のインテリセンスを持つVC#が最も好みです。

SAIの不具合

(これは2011-07-27に書いた故OCNブログの記事を加筆修正したものです)

現在判明しているPaint Tool SAI 1.1.0の不具合。Windows 7 SP1 x64、WACOM Bamboo MTE-450で確認。

  1. ファイルに名前を付けて保存した直後に、タブレットの筆圧感知がときどき効かなくなる。SAIを再起動すると直る。
  2. ビュースクロール(ハンド ツール)がときどき効かなくなる。ウィンドウを最小化、復元すると直る。
  3. ビュースクロール中心がときどき異様にずれる(画像のキャンバス領域外になる)。ウィンドウを最小化、復元すると直る。

いずれも、常に毎回発生するわけではなさそう。再現手順が不明。
その後SAI 1.2.0、Windows 8.1 x64、ドライバー5.05-7で確認した結果、(1)と(2)は修正されているような気配。

ちなみにWACOMドライバー自体にも昔から不具合があり、何かの拍子で筆圧が一切効かなくなることがあります。WACOMドライバーで不具合が発生した場合は、アプリの再起動やOSの再起動では解消できず、[タブレット設定ファイルユーティリティ]で設定をリセットしないといけなくなることがあります。

OK/Cancelボタンの配置順

WindowsMacそれぞれの、ユーザー確認ダイアログにおけるOKボタンとキャンセルボタンの位置(順序)の違いに関して、下記に考察が記載されています。

そういえば、JavaのダイアログもMacと同じ順序です(日本語版はキャンセルボタンのラベルが[取り消し]なのが気に食わないのですが)。Ubuntuとかで使われてるGnomeMacと同じらしいです。

自分は主にWindowsを使っているため、OK/キャンセルという配置が当たり前な感じなので、右側にOKがあるとかえって操作しづらく感じますが、iPhoneのキャンセル/OKという配置は特に使いづらいとは思いません。たぶんデバイスが全然違うからですね。

しかし、ゲーム(コンシューマー/PC問わず)のユーザーインターフェイスや、Webサイト・Webアプリケーションの場合、Yes/Noの選択肢は、左側にYes、右側にNoがあるほうが多いような気がします。WindowsプラットフォームのPCゲームだと、Windows GUIに合わせて、左側にYesがあったほうがユーザーとしてはとっつきやすいから、というのは分かるんですが、Xbox以外のコンシューマーゲームでも左側にYesを配置しているゲームのほうが多いんではないでしょうか。ファミコンスーパーファミコンといった、Windowsが登場する以前のゲームのUIをチェックしてみると面白いことが分かるかもしれません*1

なお、OK/Cancelボタンの配置順に関する適切な設計指針を与えてくれる記事が下記にあります。

結論としては、どちらの順序にも一理あるので、とにかくプラットフォーム(OS)の慣習に従うこと。まさに正鵠を射ています。「郷に入っては郷に従え」の精神ですね。記事で言及されているWindows UXガイドラインの該当ページは下記の[次の順番でコミット ボタンを配置します。]というセクションです。

ちなみにWindowsの配置はMS-DOSの文化(キーボード操作前提)をそのまま引き継いだ形になっているそうです。

ダメな例

自分はおうちで絵を描くのにWACOMペンタブレットを使ってるんですが、コイツのドライバーVer.5.05-7やVer.6.3.10w2の設定ダイアログ(Windows Vista/7/8だと[コントロール パネル]→[ハードウェアとサウンド]→[ペンタブレットのプロパティ]でアクセス)はCancel/OKの順序でボタン配置されてるという、いわゆるMac/Linux形式です。Windowsプラットフォームで勝手にこういうことされると違和感ありまくりですね。Mac版とボタン配置を変えるのをサボっただけなのか、もしくは
「OKボタンは右端配置が至高、だからお前らは俺のデザインに従え。Windowsの流儀? そんなんシラネ」
という頭の弱い俺様デザイナーか俺様プログラマーあたりの勝手な思想の押しつけの結果こうなったんだと思うんですが、プラットフォーム(OS)との調和がとれていない、はっきり言って汚ない設計です。少なくとも大多数のWindowsユーザーにとっては逆にMac/Linuxの流儀なんてシラネ、なわけで。

https://sygh-jp.github.io/content_hosting/software_ss/wacom_pentablet_driver_ss_2013_10_25a.png

ちなみに上記画像をよく見れば気付く人もいると思いますが、ローカライズを行なった人間は日本語の禁則処理を理解してないのでしょうか? Windows自体は普通に各国語の禁則処理を実装していると思うんですが……

余談

最近仕事で海外に存在する子会社が作ったWindowsアプリをテストしてるんですが、OK/Cancelボタンの配置順がgdgdでまったく統一感がない。国内のほかのエンジニアが操作しているところを見ていても、そのgdgd配置のせいでしょっちゅう操作ミスしています。とりあえずWindows UXガイドラインを読んで、ボタン配置を修正してくれ、と依頼しました。

ゲームコントローラーのボタン配置

Microsoft製のゲーム機、Xbox/Xbox 360/Xbox OneのコントローラーはAボタンが決定ボタンで、Bボタンがキャンセルボタンなのは任天堂の歴代ゲーム機と同じなんですが、AボタンとBボタン、そしてXボタンとYボタンの配置はそれぞれ逆になっています(ボタンの色も違います)。

任天堂SFC, DS)

 X
Y A
 B

MicrosoftXboxシリーズ)

 Y
X B
 A

ソニー(PSシリーズ、ただし海外版では文化の違いから○×の役割が逆転する)

 △
□ ○
 ×

SEGAメガドライブセガサターン

X Y Z
A B C

任天堂ソニーのゲーム機に慣れている場合、最初はXboxのボタン配置に戸惑うかもしれませんが、Xboxのゲームをやりこんでいくうちに慣れます。ただ、しばらくXboxのコントローラーばっかり使ってプレイした後で任天堂ソニーのコントローラーを使うと操作ミスすることが多いです。説明のための補助テキストラベルがあるGUIのボタンとは違って、ゲームコントローラーのボタンは手元をまったく見ないで無意識的に操作するのが当たり前なので、「慣れ」というのが大きく影響します。ファミコン時代でも、Aを決定ボタン、Bをキャンセルボタン扱いにしているゲームが主流だったと思いますが、たまに逆の割り当てを採用しているゲームをプレイすると操作ミスすることがよくありました。昔のゲームにはキーコンフィグなんてありませんから、プレイヤーが慣れるしかないわけです。
個人的な意見としては、ゲームコントローラーに関しては、やはりすべてのゲーム機・すべての文化圏でOK/Cancelに相当するボタン配置と記号だけは統一してほしいところです(どちらの順序が良いとか悪いとかいう問題ではない)。ゲームを作るとき、海外向けにローカライズする(あるいはローカライズを考慮してゲームを設計する)のはプレイステーションプラットフォームの場合が一番厄介なのでは、と思います。

余談

SEGAハードの中で自分が所持しているのはサターンだけですが、そもそも6ボタンが右側に配置されていて他ハードとは大きく異なるため、慣れのせいでOK/Cancelを操作ミスすることは少なかったと思います。なお、SFCでも格闘ゲーム向けにL/Rを含めた6ボタンが

Y X L
B A R

と右側に配置されているサードパーティ製コントローラーがありましたが、L/Rの配置が直感的でなくなること、決定ボタンとなるAボタンが端ではなく中央に来ることなどから、格闘ゲーム以外ではかなり使いづらかったです。
ちなみにSEGAドリームキャストのボタン配置はMicrosoft同様ですが、配色が違います。ドリームキャストはもともとWindows CEベースで、Microsoftも開発に関与しています。Xboxコントローラーのボタン配置はドリームキャストの影響が強いのかもしれません。
N64とかゲームキューブは一切プレイしたことがないうえにボタン配置も変態的なので今回スルーしました。

*1:ゲームの場合、Yes/Noなどの選択肢は横に並べるのではなく、縦に並べることが多いかもしれません。特にRPGでは顕著だったと記憶しています。ちなみにAdobeのCreative製品シリーズは、ダイアログではOK/キャンセルを縦に配置していますが、テキストツールなどの操作の確定/キャンセルをするアイコンボタンはWindows版でもキャンセル/確定の順です(日本語版だと×/○の順)。

64bit版Photoshop CS4/CS5の筆圧感知

PhotoshopはCS4からブラシの入り抜き(筆圧感知)がだいぶ改善されたんですが、64bit版PhotoshopではWACOMドライバー起因*1で筆圧感知がおかしくなることがあるらしいです。Windows 8.1 x64とVer.5.05-7ドライバー、Photoshop CS5で試した結果が以下*2ペンタブレットはBAMBOO MTE-450を使いました。

Photoshop CS5 64bit (12.0.4)
筆圧感知していません。ブラシ プレビューの「~」も、入り抜きがありません。
https://sygh-jp.github.io/content_hosting/software_ss/photoshop_cs5_64bit_brush_in_out_2014_10_11a.png

Photoshop CS5 32bit (12.0.4)
筆圧感知しています。ブラシ プレビューの「~」も、入り抜きがあります。
https://sygh-jp.github.io/content_hosting/software_ss/photoshop_cs5_32bit_brush_in_out_2014_10_11a.png

ちなみにSAI、ComicStudio 4(2014年現時点での正式版はともに32bit版しかない)でもきちんと筆圧が効きます。

以前(2012年5月)横浜のヨドバシで液晶タブレット使って絵を描いてみたことがあるんですが、Photoshop CS5.1(Mac OS X)のブラシの入り抜きが全然効かず困惑したことがありました。確かそのときインストールされていたのはSnow LeopardもしくはLionあたりで、Photoshopも64bitモードで動作していたのだと思います(つまりOS問わずドライバーもしくはアプリが原因で問題が起きている)。

しかし、もし64bit版のアプリケーションプログラムでは必ずこの問題が起きるのだとすればかなりゆゆしき事態です。というのもWACOMの新しいBAMBOOドライバーでは以前言及したようにWindows 8以降で例の邪魔な波紋エフェクトと動作遅延が無効化できず、さらにWPFが正常に動作しないなどという多数の致命的な不具合があるため、自分はあえてVista時代の古いドライバーを使っているのですが、もし64bit版のSAIがVistaドライバーで正常に動作しないとなると、SAIが64bit正式対応したときにまともな環境が用意できないということになります(すでに64bit対応しているCLIP STUDIO PAINTを試してみましたが、やはりどうも筆圧感知が効いてない模様)。Windows 10に関してはたぶんVistaドライバーでも動作すると思いますが、先行きが不安でもあります。旧BAMBOOユーザーは後継製品の無印Intuos、あるいは最悪Intuos Proに乗り換えることを検討せざるをえないかもしれません。しかしIntuosドライバーでもWPFにきちんと対応しているのかどうか(リリース前にWPF環境でも動作テストしているのかどうか)は怪しいです。自分は絵も描きますがVisual Studioでプログラミングも行なうので、ペンタブレットが正常に動作しないのは困ります。そしてもっとも憂鬱なのが、WACOMはバグ報告してもちゃんと真面目に対応してくれそうにないという……*3
そろそろこの閉塞感ただよう寡占市場を打破し、WACOMの鼻をへし折って一泡吹かせてくれるメーカーは現れないものでしょうか?

2014/12/27追記:
Intuos Pro M (PTH-651) に乗り換えました。Ver.6.3.10w2ドライバーをインストールし、64bit版アプリで筆圧感知されることを確認できました。ただし「デジタルインク機能を使う」というオプションを外しておかないと、ペンによるクリックが正常に動作しません。WPFを正常動作させるためにも同オプションを外す必要があるようです。また、誤操作防止のため「タッチ入力を有効にする」も外しています。なぜこんな余計な機能が付いているのか理解しかねますが……

*1:昔調べたときにはWACOMのサポートサイトにも該当問題に関するエントリーがあったんですが、2014年現在、リンク切れになっているようです。サポートサイトのエントリーURLを適切にリダイレクトせず、リンク切れにしたまま放置するなんてひどい企業だと思いませんか? 確か当時WACOMAdobeなどのアプリケーション側に問題があるとか主張していたのですが、このエントリーにはWACOMにとって不利な情報が書かれてあったので意図的に消したのかもしれません。 http://tablet.wacom.co.jp/support/faq/after/det.php?id=1248 https://web.archive.org/web/20110904114906/http://tablet.wacom.co.jp/support/faq/after/det.php?id=1248

*2:自分は筆圧や書き味のテストをするときは必ずギリシャ文字で試します。

*3:PC周辺機器の傾向として、ハードウェアは良いモノを作るけど、ドライバーやソフトウェアの品質・アフターサービスがgdgdというメーカーが非常に多いように感じます。