VC++6.0 SPなし MFC使用です。
タイトルの通りイベントハンドラ内部でイベントの起こったコントロールの
リソースIDを取得する方法はあるでしょうか?
つまり、メッセージマップのところで、
ON_BN_CLICKED(IDC_MENU_ALLPOINTS, OnPointMenu)
ON_BN_CLICKED(IDC_MENU_POINT1, OnPointMenu)
ON_BN_CLICKED(IDC_MENU_POINT2, OnPointMenu)
ON_BN_CLICKED(IDC_MENU_POINT3, OnPointMenu)
ON_BN_CLICKED(IDC_MENU_POINT4, OnPointMenu)
ON_BN_CLICKED(IDC_MENU_POINT5, OnPointMenu)
とやってるときに、 OnPointMenu() 内で、IDC_MENU_..... を取得したい
のですが。
要するに押されたボタンによってイベントハンドラ内の処理を分けたいの
です。
> ON_BN_CLICKED(IDC_MENU_ALLPOINTS, OnPointMenu)
> ON_BN_CLICKED(IDC_MENU_POINT1, OnPointMenu)
> ON_BN_CLICKED(IDC_MENU_POINT2, OnPointMenu)
> ON_BN_CLICKED(IDC_MENU_POINT3, OnPointMenu)
> ON_BN_CLICKED(IDC_MENU_POINT4, OnPointMenu)
> ON_BN_CLICKED(IDC_MENU_POINT5, OnPointMenu)
「ON_CONTROL_RANGE」を使えばご希望の事が出来ませんかね?
はずしてたらごめんなさいだけど、詳しくは以下をご覧になってみていただけますか?
それっぽい事が書かれてるようですが…。
http://www.microsoft.com/japan/developer/library/vccore/_core_handlers_for_messa
ge.2d.map_ranges.htm
直感さん、ありがとうございます。
Resource,h を手動で編集するという危険な方法を使いましたが、
解決できました。
MSG* pMsg = CWnd::GetCurrentMessage();
CWnd* pWnd = FromHandle(pMsg->hwnd);
からできないか、とも思ったのですが、ムリのようです。
> Resource,h を手動で編集するという危険な方法を使いましたが、
それはIDを順番に並べる為ですよね?
それ以外にResource.hを編集する必要がないと思ったので。
もしそれ以外の良い方法の為でしたら、教えて下さいませ。
> Resource,h を手動で編集するという危険な方法を使いましたが、
> 解決できました。
あっ、もしかしてコントロールのシンボル(ID)の値が連続していなかったので、
単純に範囲指定できない状態だったということでしょうか?(^^;
VisualStudio6.0でしたら[表示]->[シンボルブラウザ]というものを起動して、
そこで既存IDの値を変更したり、新規にシンボルを追加したり出来るようです。
コントロールに既に割り当てられているIDの場合、単純に値を変更出来ない場合も
ありますが、その場合はテンポラリのIDをとりあえず新規作成して
コントロールに割り当て、その後元のIDをもう一度新規作成で順番に
作成すれば、安全に連続した値を割り当てられたような気がします。
> > Resource,h を手動で編集するという危険な方法を使いましたが、
> それはIDを順番に並べる為ですよね?
> それ以外にResource.hを編集する必要がないと思ったので。
> もしそれ以外の良い方法の為でしたら、教えて下さいませ。
そなんすよね。
リソースIDは、VCのリソースエディタ君がかってに割り振るので、
リソースIDが連続しているものしか使えない。そうでない場合は
上記のような気が指す行為をせねばいかん。
試行錯誤したところ、GetFocus() 使えば、押されたボタンが
解るのでゃないかと思いました。
CWnd* pWnd = CWnd::GetFocus();
CString strCaption;
pWnd->GetWindowText(strCaption);
とやると、押されたボタンがイベントハンドラ内部で得られる
ようです。
上記の方法でマズい場合、ツッコミお願いします。
ちなみに、
> MSG* pMsg = CWnd::GetCurrentMessage();
> CWnd* pWnd = FromHandle(pMsg->hwnd);
で得られる CWnd は、ダイアログのでした。
>> MSG* pMsg = CWnd::GetCurrentMessage();
>> CWnd* pWnd = FromHandle(pMsg->hwnd);
>
> で得られる CWnd は、ダイアログのでした。
ボタンクリックの通知は、WM_COMMANDですから、
wNotifyCode = HIWORD(wParam); // notification code
wID = LOWORD(wParam); // item, control, or accelerator identifier
hwndCtl = (HWND) lParam; // handle of control
です。
ただ、リソースファイルを手作業で修正しても別に問題無いと思います。
MSDN「テクニカルノート35」辺りが参考になるのでは。
> とやると、押されたボタンがイベントハンドラ内部で得られる
> ようです。
>
> 上記の方法でマズい場合、ツッコミお願いします。
タイミング的にコントロールIDの値の再割り当ての書き込みが見落とされて
しまったっぽいのですが、(^^; とりあえず連続した値の割り振りは可能です。
(5つめの書き込みを参照(^^;)
ところで、フォーカスの当たっているコントロールのキャプションを
ゲットするという作戦だと思うのですが、プログラムの仕様変更とか他の人が
手を入れる可能性というのは無いと考えても良いでしょうか?
いや、もし件の処理をする直前に(同じイベントハンドラ内で)SetFocusとか
されちゃったら押されたボタンとは違うボタンのキャプションがゲットされたり
しないかなぁと思いまして…。(^^;
まぁフォーカスを明示的に設定するのって、初期化の時かボタンが押されたときの
エラー処理なんかが多いとは思うので、あまり問題ないとは思いますが…。
すいません、レスが交錯してしまいました>直感さん。
> VisualStudio6.0でしたら[表示]->[シンボルブラウザ]というものを起動して、
> そこで既存IDの値を変更したり、新規にシンボルを追加したり出来るようです。
リソースIDはこちらの自由になるのですね。
とすると連続IDを作っておいて、それらに同一のハンドラをマップするというの
も安心して使えますね。
いや、ハンドラ内でGetFocusして押されたボタンをGetするというテも捨てがた
かったんですが、得られたCWndの識別はキャプションかなんかでやるしかない。
とすると、switch case 文使えないし、ナニかと不便そうなので、DN_CONTROL_RANGE
でいきます。(それが一番スナオそうだ)
dairygoods さん、ありがとうございます。
> wID = LOWORD(wParam); // item, control, or accelerator identifier
この部分がリソース取得部分ですね。
この方法も捨てがたいなぁ。
> リソースIDは、VCのリソースエディタ君がかってに割り振るので、
> リソースIDが連続しているものしか使えない。そうでない場合は
> 上記のような気が指す行為をせねばいかん。
あ、やっぱりそうなんですね。
直感野郎Aチームさんがおっしゃっているシンボルブラウザであらかじめ使用するだけのIDを確
保しておき、初期設定の段階で自前でメニューを追加という手はどうでしょう。
>VC++6.0 SPなし MFC使用です。
最低SP3はあてましょう。確かコンパイラ周りのバグがあったようです。
シンボルブラウザもあまり万能ではなさそうなので、例えば連続したIDが大量に
欲しいとなると、もしかしたら途中で値が飛んでしまうことがあるかもしれません。(^^;
まぁ、新規作成の場合は一応値を自分で設定出来ますけど…。
例えば10個のIDを作ろうとして、値が自動的に100から割り当てられて行ったときに、
105とかいう値のIDが既存だったりする場合には連続にならないかもしれないです。(^^;;;
ちなみに昔、自分で設定したのか自動で設定されたのか、なんらかの問題が発生した
ためか、IDに値「0」が割り当てられてしまったことがあり、イベントハンドラが
起動しないという現象に慌てたことがあります。(^^;;;
dairygoods さん、ありがとうございます。
ダイアログのイベントハンドラ内部で、
const MSG* pMsg = GetCurrentMessage();
int nResourceId = (int)pMsg->wParam;
CWnd* pWnd = GetDlgItem(nResourceId);
pWnd->GetWindowText(strCaption);
AfxMessageBox(strCaption);
とやったらうまくいってました。
上記方法でいきます。
加発さん、忠告ありがとうございます。
> >VC++6.0 SPなし MFC使用です。
> 最低SP3はあてましょう。確かコンパイラ周りのバグがあったようです。
あわてて、SP5入れました。
(しかし、ナゼSP情報がスプラッシュ画面にもVersion情報にも表示されん
のだ? VBの方は両方出るのに)
ウヨ曲折ありましたが、解決とさせていただきます。