スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コンテキストメニュー拡張・事前調査その3

やっぱり調べてみると結構判断に迷うところが多いですねー。ログを出すようにしてみて良かったです。IContextMenu::QueryContextMenuのindexMenuに0が来ていると書きましたが、ショートカットファイルの時には1が来ていました。ショートカットファイルの時には、メニューアイテムを追加すべきでないとヘルプなどには書いてありますが、ショートカットファイルそのものを処理すべきなのか、リンク先のファイルを処理すべきなのか、また対象の切り替え処理はどのように行うべきなのかはなかなか難しいところです。実際に試したことがある人は分かってもらえるかと思いますが。
ネットで探しても情報が少ない上に、必ずしもそれが正しい情報であるとは限らないんですよね。(私の実装方法も同様です。)ヘルプに曖昧な点が多いために、実装方法が個々の判断に委ねられているんですね。クライアントとサーバーが作用する点に関してはきちんと仕様を書いておいて欲しいものです。メニューのセパレータとかね。

さて、今日はIContextMenu::GetCommandStringについて書きます。こいつも簡単ではないです。
HRESULT GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax);

idCmdはハンドラ内のメニューアイテムのオフセットになります。uFlagsはこの関数の呼び出し理由のような感じです。おおざっぱに言えばGCS_HELPTEXT、GCS_VERB、GCS_VALIDATEのいずれかになります。GCS_HELPTEXTは、コンテキストメニューのアイテムをポイントしたときにフォルダのウィンドウ等のステータスバーに表示されるヘルプテキストです。GCS_VERBは、メニューアイテムの言語に依存しないコマンド名のような感じかと思われます。コンテキストメニュー拡張の場合に、シェルからどのような用途に使われているのかが不明です。GCS_VALIDATEは、メニューアイテムが存在しているかどうかを検査するために使われます。が、シェルから呼び出されている気配が今のところありません。

気をつけなければいけないのが、これらが全てANSI版とUNICODE版があることです。つまりGCS_HELPTEXTAとGCS_HELPTEXTWのようになっているわけです。調べた限りでは、XPにおいてはGCS_HELPTEXTはANSI版とUNICODE版の両方が呼び出されているようです。これに対し、GCS_VERBはUNICODE版しか呼び出されていませんでした。(Windows95ではANSIしか呼び出されないらしい。)これは、ビルドがANSIで行われているか、UNICODEで行われているかに依存しません。GCS_HELPTEXTは、ビルド時の言語設定によってGCS_HELPTEXTAまたはGCS_HELPTEXTWに展開されますが、実際にどちらが呼ばれるかは、使用環境によるわけです。従って、使用環境に依存しない実装にするためには、すべてのA版とW版をいちいち明示的に書いてあげないといけないと思われます。
ちなみに、文字列のコピー先であるpszNameはLPSTRとなっていますので、W版の時にはLPWSTRにキャストしてあげる必要があります。
実際に実装する場合に、コード上にANSI版とUNICODE版の文字列を1つずつ定義するのはスマートではないように思われますので、

if (uFlags == GCS_VERBA || uFlags == GCS_VERBW)
{
    CString strName;
    switch (idCmd)
    {
    case 0:
        strName = _T("Test1");
        break;
    case 1:
        strName = _T("Test2");
        break;
    case 2:
        strName = _T("Test3");
        break;
    default:
        return E_INVALIDARG;
    }

    if (uFlags == GCS_VERBA)
    {
        ::lstrcpyA(pszName, CT2A(strName));
    }
    else
    {
        ::lstrcpyW((LPWSTR)pszName, CT2W(strName));
    }
}

のようにするのはどうでしょうかね?

cchMaxは、コピー先バッファの最大文字数(おそらく最大バイト数ではない?)です。この値に関わらず、コピーする文字列は40文字以内にすることが推奨されています。しかし、ヘルプ文字列とコマンド文字列の区別がついていないので、どちらについてそうなのかがハッキリしないところではあります。また、日本語は想定されていないでしょうから、ヘルプ文字列が全角である場合には、20文字くらいの方がいいのかもしれません。cchMaxに渡される実際の値は、uFlagsによってバラバラです。64の時もあれば600の時もありました。これに関わらず40文字程度が推奨されるということかと思われます。おそらくステータスバーの表示領域を考えてのことではないかと考えられます。

戻り値についてですが、成功ならばNOERROR、そうでなければOLE定義のエラー値を返すようにとヘルプには書かれています。実際に、ネット上にあるコードでは、例えばidCmdが対応していない不正な値の場合にはE_INVALIDARGSを返しているコードが多かったです。しかしヘルプをよく見ると、uFlagsがGCS_VALIDATEの場合には、メニューアイテムが存在すればS_OK、そうでなければS_FALSEを返すようにとあります。NOERRORとS_OKはともに0なので良いんですが、S_FALSEとE_INVALIDARGSは全く違う値ですので問題があるかもしれません。そもそもGCS_VALIDATEが呼ばれている気配は無いんですけどね。まあ、このあたりもよく分からない点ではありますが、できるだけ仕様に忠実に実装しておくのが基本かと思います。
関連記事

comment

Secret

カレンダー
03 | 2017/04 | 05
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
カテゴリー
最近の記事
最近のコメント
タグ

カメラ GH2 GH3 

ブログ内検索
月別アーカイブ
RSSフィード
プロフィール
●オンラインソフト作家。しかし長らく活動休止中。
ソフトウェア

●Dさんの長押しIME起動2
●IME+ (仮称)

・Dさんの長押しIME起動。
・Dさんの日本語じゃなきゃイヤン。
・Dさんの名前変更お手伝い。
・Dさんのダイヤルアップ接続お手伝い。
・DさんのWindows終了お手伝い。

・お忍びランチャー。
・お忍びリネーム。
・デジくいっくサーチ!
・Simple Remote
・計算王?

※過去の開発ソフトの一部はリンク先からダウンロードできます。

リンク
FC2カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。