![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
「WinMainCRTStartup の オーバーライド?」
_____________________________________________________________________________________
半月前、 http://oshiete.goo.ne.jp/qa/6949019.html 「フォーカス位置を取得したい」
で質問したものですが、少しは進んだのですが、困りました。
そこで、また質問させて頂きます。
【やりたいこと】できるだけ、MFCでつくったコードは、流用しつつ、最後にフォーカスしたオブジェクト名(クラス名?)を取得したいのですが・・・、
C言語の時は、int main()からプログラムを書くと…いう、うろ覚えですが、
MFCウィザードで作ったアプリでは、
CWinApp::InitInstance(); が入り口らしく、ソースコードにも記述されていましたが、
static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); が使いたいが為に
「WinMainを実行したい」と思い、次に「WinMainCRTStartup」という言葉に辿り着き、
「WinMainをカスタマイズするには、WinMainが呼び出すCWinAppのメンバ関数(例:InitInstance等)
をオーバーライドして行います。」という言葉に辿り着きました。
要は、MFC使用でWinMainをカスタマイズしたいのですが、
「"MFC利用" WinMain VC++」などの言葉で、Web検索してみたのですが、
やはり、分からないです。
Enterキー、マウスのクリック、Escキーなどのキーボードイベントも取得したいですが、
今の所は、▼ここから
case WM_COMMAND:
switch (LOWORD(wp)) {
case IDC_COMBO_OK_BOX:
if (HIWORD(wp) == EN_SETFOCUS){
KeywordDlg KeywordDlg_CLASS;
KeywordDlg_CLASS.LastFocus = _T("OK_BOX");
//MessageBox(NULL ,_T("OK_BOX"),MB_YESNOCANCEL);
}
case IDC_COMBO_NG_BOX:
if (HIWORD(wp) == EN_SETFOCUS){
KeywordDlg KeywordDlg_CLASS;
KeywordDlg_CLASS.LastFocus = _T("NG_BOX");
}
}
return 0;
▲ここまでのソースが通れば、良いです。
OKは、マッチする言葉、NGは、マッチしない文字列を入れたコンボボックスを
意味しています。
LastFocusは、文字型グローバル変数です。
【↓】(1) 「VC++のダイアログベースでAPIを使う方法はありますか?」
http://detail.chiebukuro.yahoo.co.jp/qa/question …
という、回答がまさに僕のやりたいことですが、もう少し、補足が欲しいところです。
何か分かりやすく書かれたサイトや参考書はないでしょうか?
(MFCを使う事、.NETなどのランタイムを必要としないもの、VC++に限るという観点から教えて下さい)
まだ、VC買って数ヶ月程度で、MSDNで調べても分からない事もあります。
【↓】(2) これもヒントになりそうですが・・・ちょっと長いです。
http://social.msdn.microsoft.com/Forums/ja-JP/vc …
【↓】(3) これは、ずばりだと思いますが、難しいです。
http://homepage1.nifty.com/kazubon/progdoc/tcloc …
VCで、MFC利用 でつくったものは エントリポイントがWinMainCRTStartupになる事は分かりました。
またWinMainにしたときは、エラーは出ませんでした。そもそも実行されていないだけかも。
後、気になった点は、2ちゃんねるのログで・・・
/entyオプションでエントリポイントを変えなさい
WinMainCRTStartupという名前の関数を作らないとだめなのでは?
・・・と書かれていた事ぐらいです。
回りに聞く人がいなくて困っています。トライ&エラーはしてるつもりです。
オーバーライドというのは、前にここでも質問しましたが、まだ自分のモノになったとは、
言えません。(教えて下さった方すみません)
【ファイル】FileListCreator.cpp
class CFileListCreatorDlg : public CDialogEx
{
private:
static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
LRESULT WindowProc( HWND, UINT, WPARAM, LPARAM );
//static unsigned __stdcall Thread( void * );
//int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,PSTR lpCmdLine , int nCmdShow );
void WINAPI WinMainCRTStartup(void);
};
【ファイル】FileListCreatorDlg.cpp
void WINAPI WinMainCRTStartup(void){
HWND hwnd;
MSG msg;
WNDCLASS winc;
HINSTANCE hInstance;
hInstance = GetModuleHandle(NULL);
winc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
winc.lpfnWndProc = (WNDPROC)WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL , IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL , IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("HELLO");
CString szClassName = _T("TEST");
CString szWindowText = _T("Hello,World");
hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, szClassName, szWindowText,
0, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ExitProcess(msg.wParam);
}
【分からない所】
WndProc
に赤い波線が付いていて、
エラー 47 error C2065: 'WndProc' : 定義されていない識別子です。
となっており、
static に変えているのに、エラーが起こります。
void WINAPI WinMainCRTStartup(void) にした時の疑問です。
_____________________________________________________________________
本題の質問ですが、MFCを利用しつつ(今まで作ったコードを残しつつ)
目的の機能が実装可能か?が、それだけでも知りたいです。教えてください!
No.3ベストアンサー
- 回答日時:
子ウィンドウに対するハンドラが標準で用意されていないメッセージを処理したい場合は、PreTranslateMessageをし追加ます。
ダイアログの仮想関数追加でPreTranslateMessageを追加して、pMsgの内容から必要なメッセージだと判断した時に処理するようにします。
今回の場合は、
pMsg->message が WM_LBUTTONDOWN
pMsg->hwnd が m_xcCombo_OK_BOX.m_hWmd
と等しい場合に処理すればいいんじゃないでしょうか。
ただ、WM_LBUTTONDOWNで処理してしまうと、ドラッグで文字を選択した場合などは、問題があると思います。また、コンボボックスがWM_LBUTTONDOWNを処理してからでないと、キャレットの位置も変わっていないでしょうし。
WM_LBUTTONUPで処理を行えばいいような気がします。
(そのままですが・・・)
「ダイアログの仮想関数追加でPreTranslateMessageを追加 コンボボックス」
・・・で調べました。
貴重なキーワードを頂き、感謝しています。また、最後まで教えて下さり、ありがとうございました。
方向性が定まっていないで、とてつもなく面倒な事をするところでしたυ
それとは別に、一つ ミスタイプがありました。正しくは「->m_hWnd」ですね。
自分では思いつかないのに、あげ足取りですみません。
PreTranslateMessageは他にも応用が利きそうです。質問してよかったです。
以下、参考までに・・・
【KeywordDlg.h】
class KeywordDlg : public CDialogEx
{
DECLARE_DYNAMIC(KeywordDlg)
public:
KeywordDlg(CWnd* pParent = NULL); // 標準コンストラクター
virtual ~KeywordDlg();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート
// 生成された、メッセージ割り当て関数
virtual BOOL OnInitDialog(); //追加2011.08.17
virtual BOOL PreTranslateMessage(MSG* pMsg); //追加2011.09.02
DECLARE_MESSAGE_MAP()
・・・
};
【KeywordDlg.cpp】
// PreTranslateMessage
BOOL KeywordDlg::PreTranslateMessage (MSG* pMsg)
{
switch (pMsg->message)
{
//case WM_LBUTTONDOWN:
// break;
case WM_LBUTTONUP://コンボボックスの▼が押された時のみ拾ってくれるみたいで、無くても良いみたいですυ
//HWND m_hWnd;
//if(pMsg->hwnd == GetDlgItem(IDC_COMBO_OK_BOX)->m_hWnd ){
// LastFocus = _T("OK_BOX");
// DWORD dwSel;
// if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){
// dwSel_OK = dwSel;
// }
// //MessageBox(_T("マウスが押されました"));
//}
break;
case WM_MOUSEMOVE://カーソルの移動そのものを拾う //コンボボックスを横切っただけでも、拾われそうですが(?)、問題なしみたいです。
if(pMsg->hwnd == GetDlgItem(IDC_COMBO_OK_BOX)->m_hWnd ){
LastFocus = _T("OK_BOX");
DWORD dwSel;
if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){
dwSel_OK = dwSel;
}
//MessageBox(_T("カーソルが移動しました"));
}
break;
default:
break;
}
return CDialog::PreTranslateMessage (pMsg);
}
~ 一部抜粋 ~
void KeywordDlg::OnCbnEditchangeComboOkBox()
{
LastFocus = _T("OK_BOX");
DWORD dwSel;
if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){
dwSel_OK = dwSel;
}
}
void KeywordDlg::OnCbnSetfocusComboOkBox()
{
((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetEditSel(-1,-1);//選択なしで、最後の文字位置にカーソルを置く
}
void KeywordDlg::OnCbnKillfocusComboOkBox()
{
LastFocus = _T("OK_BOX");
}
void KeywordDlg::OnBnClickedBtnAsterisk()
{
InsertStrIntoKeywords(_T("*"));
}
void KeywordDlg::InsertStrIntoKeywords(CString str){
CString ComboStr = _T("");
DWORD dwSel;
if (LastFocus == _T("OK_BOX")){
((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetWindowText(ComboStr);
dwSel = dwSel_OK;
if (dwSel != CB_ERR){
((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));
dwSel_OK++; //連続して文字を挿入する場合を考慮
}
}else if (LastFocus == _T("NG_BOX")){
((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->GetWindowText(ComboStr);
dwSel = dwSel_NG;
if (dwSel != CB_ERR){
((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));
dwSel_NG++; //連続して文字を挿入する場合を考慮
}
}else{
dwSel = CB_ERR;
return;
}
}
(変数の追加で、カテゴリを「Control」すればいいと思うのですが、万が一今までの記述で
不具合があるといけないので、今回は DDX_Control で設定した物は使わず、直で指定しています。)
◆Win32 メッセージ一覧
http://wisdom.sakura.ne.jp/system/winapi/windata …
たった、一文字を挿入したいだけなのに~ぃ と思いましたが、出来て良かったです!
本当にありがとうございましたm(_ _)m
しばらくして、締め切ります。
No.2
- 回答日時:
ウィンドウハンドルがNULLってことは、m_xcCombo_OK_BOXがコントロールとうまく結びついていないということです。
DDXを使っているなら、DoDataExchange内のDDX_Controlの記述が正しいか確認してみてください。
この回答への補足
返事が遅くなってしまい、大変申しわけありません。
色々、思考錯誤したのですが、まだできません。しかし、僕のソフトにとっては
絶対にいる機能ではないです。ただ、勉強のため お付き合いくださるなら、うれしいです。
コンボボックスに文字を入力した直後に 「*」を挿入する機能はできました。
ありがとうございます。しかし、以下のようなケースでは「*」が思った位置に挿入できません。
その為、
◆コンボボックスで左マウスが押されたか?を拾いたいのですが、
(コンボボックスでWM_LBUTTONDOWNが押されたか?)
クリックメッセージハンドラ
void 【コンボボックス】.OnLButtonDown(UINT nFlags, CPoint point){}はないので、
コンボボックスの値が変わらず、マウスカーソルだけが動くときに、インデックスを
拾えないです。OnCbnEditchangeComboOkBox()の部分です。
エディットボックスならできるのかもしれませんが。
◆CComboBox クラス(でも、ちょっと難しいです↓後でやってみます。今は時間切れという感じです)
http://msdn.microsoft.com/ja-jp/library/12h9x0ch …
メモ WM_KEYDOWN メッセージと WM_CHAR メッセージを処理する場合は、コンボ ボックスのエディット コントロールとリスト ボックス コントロールをサブクラス化し、CEdit と CListBox からクラスを派生させ、その派生クラスにこれらのメッセージのハンドラーを追加する必要があります。 詳細については、 http://support.microsoft.com/default.aspx?scid=k … および「CWnd::SubclassWindow」を参照してください。
//「コンボ ボックスのエディット コントロールとリスト ボックス コントロールをサブクラス化し、CEdit と CListBox からクラスを派生させ、」という所がすぐには出来ません。
【KeywordDlg.h】
#include "afxwin.h"
// KeywordDlg ダイアログ
class KeywordDlg : public CDialogEx
{
・・・
public:
CComboBox m_xcCombo_OK_BOX;
CComboBox m_xcCombo_NG_BOX;
DWORD dwSel_OK;
DWORD dwSel_NG;
CString LastFocus;
void InsertStrIntoKeywords(CString str);
afx_msg void OnBnClickedBtnAsterisk();
};
【KeywordDlg.cpp】マッチする文字を入れるOK_BOXの部分を主に載せます。
BOOL KeywordDlg::OnInitDialog(){
//WndProc;
LastFocus = _T("NotSelected");
return true;
}
void KeywordDlg::OnCbnEditchangeComboOkBox()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
LastFocus = _T("OK_BOX");
DWORD dwSel;
//if ((dwSel = m_xcCombo_OK_BOX.GetEditSel()) != CB_ERR){
if ((dwSel = ((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetEditSel()) != CB_ERR){
dwSel_OK = dwSel;
}
CString tempStr;
tempStr.Format(_T(" LOWORD(dwSel):%d \r\n HIWORD(dwSel):%d \r\n\r\n"),(int)LOWORD(dwSel),(int)HIWORD(dwSel));
TRACE(tempStr);
//ここでは、値が変わらない&カーソルのみ動く…ということが、拾えない
}
void KeywordDlg::OnCbnSetfocusComboOkBox()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetEditSel(dwSel_OK,dwSel_OK);
}
void KeywordDlg::OnBnClickedBtnAsterisk()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
InsertStrIntoKeywords(_T("*"));
}
void KeywordDlg::InsertStrIntoKeywords(CString str){
CString ComboStr = _T("");
DWORD dwSel;
if (LastFocus == _T("OK_BOX")){
((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->GetWindowText(ComboStr);
dwSel = dwSel_OK;
if (dwSel != CB_ERR){
((CComboBox*)GetDlgItem(IDC_COMBO_OK_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));
}
}else if (LastFocus == _T("NG_BOX")){
((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->GetWindowText(ComboStr);
dwSel = dwSel_NG;
if (dwSel != CB_ERR){
((CComboBox*)GetDlgItem(IDC_COMBO_NG_BOX))->SetWindowText(const_cast<LPTSTR>(static_cast<LPCTSTR>(ComboStr.Left(LOWORD(dwSel)) + str + ComboStr.Right(ComboStr.GetLength()-LOWORD(dwSel)))));
}
}else{
dwSel = CB_ERR;
return;
}
}
変数に入れてない、冗長で見にくいですが、お許し下さい。
後、「イベントハンドラの追加」でも#1に書かれている事はできますね。知りませんでした。
メンバ変数の追加ウィザードで、追加したときに、カテゴリを「Value」にしたのが、問題だったのか、
DDX_Controlの動作がうまく行かなかったのかもしれません。
No.1
- 回答日時:
別に、そんな大変なことをしなくても、コンボボックスのCBN_SETFOCUSに対するハンドラを用意すればいいんじゃないですか?
数が多くて、1つ1つハンドラを作成するのが大変とかであれば、親ウィンドウ(ダイアログなど)のPreTranslateMessageで処理できるはずです。
MFCを使っていても、独自にCreateWindowでウィンドウを作成するとか、ウィンドウプロシージャを別のものにするとかはできますが、MFCの動作をよく理解していないと大変苦労します。MFCの枠組み内でできることは、利用したほうが無難です。
この回答への補足
雷マークを押して、追加するのですね。どおりて、簡単すぎてググっても
ダメなはずです。(遅くなってすみません。その他の部分をずっと考えてました。)
とりあえず、フォーカスを検知はできましたが、下のコードすら通らないです。
僕のMFCライブラリは壊れてしまったのでしょうか?
> FileListCreator.exe!CComboBox::GetEditSel() 行 854 + 0x2d バイトC++
+ m_hWnd 0x00000000 {unused=??? }HWND__ *
+ this 0x0292ae18 {CComboBox hWnd=0x00000000} const CComboBox * const
以下のようなエラーが出て、中断せざるを得ません。続けると、ちゃんと文字も入っているのですが、
Get,Setする所が悪さをしているように思います。
GetEditSel()
m_xcCombo_OK_BOX.GetWindowTextW(ComboStr);
Setするのは、他のボタンを押したときです。カーソル位置に一文字「*」などを挿入したいです。
LeftとRightを使うだけなので、カーソルが何文字目にあるか?さえ分かれば作れます。
くだらない(?)機能にお手間を取らせてすみません。
BOOL KeywordDlg::OnInitDialog(){
//WndProc;
LastFocus = _T("NotSelected");
return true;
}
void KeywordDlg::OnCbnEditchangeComboOkBox()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
LastFocus == _T("OK_BOX")
DWORD dwSel;
// Set the selection to be all characters after the current selection.
if ((dwSel = m_xcCombo_OK_BOX.GetEditSel()) != CB_ERR){
//m_xcCombo_OK_BOX.SetEditSel(HIWORD(dwSel), -1);
//CString tempStr;
//tempStr.Format(_T("%d"),(int)dwSel);
//MessageBox(tempStr);
dwSel_OK = dwSel;//マッチキーワードボックス内の文字位置をグローバル変数に退避
}
}
途中報告でした。回答ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- Visual Basic(VBA) 動かなくなってしまった古いVBAを動くようにしたい 8 2022/09/20 13:57
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- PostgreSQL DBFluteについて質問です。 環境:PostgreSQL java8 前提:webアプリケーショ 1 2022/07/07 00:49
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
他のウィンドウのボタンを自動...
-
点滅で知らせる方法
-
MQプログラミング MQGetの手法...
-
マウスの状態の取得
-
VB6でシャットダウン、ログオフ...
-
ElseIfの使い方。
-
WM_CTLCOLORDLG
-
キーボード・フックのアプリを...
-
VBでRegisterWindowMessage関数...
-
vbaから他のアプリを終了
-
メッセージボックスの選択ボタ...
-
デスクトップ上のアイコンの位...
-
マインクラフト(pc版)で座標...
-
エクセルで作った新しいウイン...
-
GLUTでのウィンドウの左上のア...
-
グラフの交点の求め方(Excel)
-
MFCでOnPaintのタイミング
-
リストボックスの同期
-
コントロールの書式設定で、“コ...
-
ゲームでは結局どっちが良いの?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
vbaから他のアプリを終了
-
msgboxの表示位置
-
他のウィンドウのボタンを自動...
-
メッセージボックスの選択ボタ...
-
SetWindowText関数について
-
VBAでコントロールのハンドルを...
-
Excel VBA で外部アプリケーシ...
-
VB.netでFindWindowExやると・...
-
メッセージハンドラ
-
点滅で知らせる方法
-
CloseHandle()
-
システム例外のメッセージを変...
-
WM_NCLBUTTONUPについて
-
デスクトップ上のアイコンの位...
-
メッセージループについて
-
キーボード・フックのアプリを...
-
VBでRegisterWindowMessage関数...
-
WM_CTLCOLORDLG
-
windowsメールスロットについて...
-
マウスフックについて
おすすめ情報