MFC は、一般的に使用される多くのコントロールをカプセル化し、明確なインターフェイスを提供せずにクラス名をカプセル化します。win API を使用してウィンドウ プログラムを作成するには、最初のステップはウィンドウ クラスを登録することです。
このとき、クラス名とタイトル名が一緒に登録されるので、クラス名も非常に簡単に設定できるはずですが、残念ながら、これは MFC がこれを行っていないためかもしれません。連続的に変更できますが、クラス名は変更できません。ウィンドウのクラス名は Create によって決定されます。Create の前に、ウィンドウの Create をパラメータとして選択する必要があります。最終的には CreateEx に進みます。 CreateEx ではさらに明確になります。
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam /* = NULL */){ return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle , rect.left、rect.top、rect.right -rect.left、rect.bottom -rect.top、pParentWnd->GetSafeHwnd()、(HMENU)(UINT_PTR)nID、lpParam);}BOOL CWnd::CreateEx(DWORD) dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam){ ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClassName) || Afx はValidAtom( lpszClassName )); ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName)); // いくつかの共通作成パラメータの変更を許可します。 cs.dwExStyle = cs.lpszClass = lpszWindowName;スタイル = dwStyle; cs.cx = nWidth; cs.hMenu = nIDorHMenu; ) { PostNcDestroy(); return FALSE; } AfxHookWindowCreate(this); cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);#ifdef _DEBUG if (hWnd == NULL) { TRACE(traceAppMsg, 0, "警告 : ウィンドウの作成に失敗しました: GetLastError は 0x%8.8 を返しますXn", GetLastError()); }#endif if (!AfxUnhookWindowCreate()) PostNcDestroy(); // CreateWindowEx がすぐに失敗した場合のクリーンアップ if (hWnd == NULL) return FALSE; ASSERT(hWnd == m_hWnd); // send msg フックに設定する必要がある return TRUE;}
最終的に::AfxCtxCreateWindowEx に到達することがわかります。ここで CreateWindowEx が呼び出され、ウィンドウが作成されることが簡単にわかります。
先頭に PreCreateWindow(cs) があり、cs が PreCreateWindow で処理された後、::AfxCtxCreateWindowEx に渡されて処理されます。
::AfxCtxCreateWindowEx は CreateWindowEx に転送されます。cs.lpszClass はクラス名であり、AfxCtxCreateWindowEx が善意であることが明らかです。
次のように、PreCreateWindow をオーバーロードしてクラス名を変更できます。
// TODO: ここに特殊なコードを追加するか、基本クラスを呼び出します。 //VERIFY(AfxDeferRegisterClass(AFX_WND_REG)) //cs.lpszClass = AfxRegisterWndClass(NULL); 0, sizeof(WNDCLASS)); // デフォルトは wndcls.style = CS_DBLCLKS | CS_VREDRAW; // 独自のウィンドウ プロシージャを指定できます wndcls.lpfnWndProc = ::DefWindowProc; ; wndcls.hIcon = NULL; // または別のアイコンをロードします wndcls.hCursor =NULL; wndcls.lpszMenuName = NULL; wndcls.lpszClassName = _T("MyNewClass"); // 新しいクラスを登録し、失敗した場合は終了します if(!AfxRegisterClass(&wndcls)) { TRACE("クラスの登録に失敗しましたn") } cs.lpszClass = wndcls.lpszClassName; // CWnd::PreCreateWindow(cs) を返します。
実際には、登録されたクラス名の文字列を CreateWindowEx に渡すためです。上記のコードのコメントから判断すると、システムが className を生成できるようにする AfxRegisterWndClass メソッドも使用しました。 CWnd::PreCreateWindow は私の希望に合わないのでコメントアウトしました。実際には何も入っていません。これは単なる判断です。 MFC では、CWnd の他の派生クラスはそれほど単純ではありませんが、クラス名を変更してこのメソッドをオーバーロードするだけでほとんど問題ありません。
はい、ほとんどの場合は可能ですが、残念ながら、このメソッドは CWnd::Create を使用しないため、Dialog では機能せず、回避することはできません。
PreCreateWindow が表示されます。ダイアログ ボックスのこのメソッドをオーバーロードできます。ブレークポイントは壊れません。 CDialog の作成はシステムの API を使って直接行うことができ、わざわざ CWnd から CReateWindowEx に転送する必要がないため、上記のメソッドを使用してダイアログ ボックスのクラス名を変更することはできません。
その作成コードを見てください。
BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd){ ASSERT(IS_INTRESOURCE(lpszTemplateName) || AfxIsValidString(lpszTemplateName)); m_lpszTemplateName = lpszTemplateName // ヘルプに使用 if (IS_INTRESOURCE(m_lpszTemplateName) && m_ nID ヘルプ == 0) m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);#ifdef _DEBUG if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE)) { ASSERT(FALSE); // 無効なダイアログ テンプレート名 PostNcDestroy() // 作成がすぐに失敗した場合はクリーンアップします。 #endif //_DEBUG HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG); BOOL bResult = CreateIndirect(hTemplate, pParentWnd); 、hInst ) ; FreeResource(hTemplate); を返します。
CDialog がリソースによって作成されることがわかります。この方法で、リソース スクリプト内でクラス「ダイアログ クラス名」を定義し、ダイアログ ボックスで domodal または Create の前にこのクラス名を登録し、モーダルを待ちます。作成してください。
この期間中、私は他の側面で忙しかったので、MFC パッケージ化メカニズムについて多くを忘れていました。復習としてコードをトレースします。