MFC kapselt viele häufig verwendete Steuerelemente und kapselt die Klassennamen, ohne eine offensichtliche Schnittstelle bereitzustellen. Um ein Fensterprogramm mit der Win-API zu schreiben, besteht der erste Schritt darin, die Fensterklasse zu registrieren.
Zu diesem Zeitpunkt werden der Klassenname und der Titelname zusammen registriert, sodass der Klassenname ebenfalls sehr einfach sein sollte. Der Grund dafür kann sein, dass der Fenstername nicht vorhanden ist kann fortlaufend geändert werden, der Klassenname jedoch nicht. Der Klassenname des Fensters wird durch „Create“ bestimmt. Als Parameter müssen Sie „Create“ für das Fenster auswählen bei CreateEx. Viel klarer
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)); style = dwStyle; cs.y = y; cs.cx = nHeight; cs.hMenu = nIDorHMenu; ) { PostNcDestroy(); return FALSE; } AfxHookWindowCreate(this); HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs. cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);#ifdef _DEBUG if (hWnd == NULL) { TRACE(traceAppMsg, 0, "Warnung: Fenstererstellung fehlgeschlagen: GetLastError gibt 0x%8.8 zurück Xn", GetLastError()); }#endif if (!AfxUnhookWindowCreate()) PostNcDestroy(); // Bereinigung, wenn CreateWindowEx zu früh fehlschlägt if (hWnd == NULL) return FALSE; ASSERT(hWnd == m_hWnd); // sollte im Send Msg Hook gesetzt sein return TRUE;}
Sie können sehen, dass es schließlich::AfxCtxCreateWindowEx erreicht. Sie können leicht erkennen, dass CreateWindowEx hier aufgerufen wird, um ein Fenster zu erstellen.
Davor befindet sich ein PreCreateWindow(cs), und nachdem cs von PreCreateWindow verarbeitet wurde, wird es zur Verarbeitung an ::AfxCtxCreateWindowEx übergeben
::AfxCtxCreateWindowEx wird an CreateWindowEx übergeben. cs.lpszClass ist der Klassenname, was deutlich macht, dass AfxCtxCreateWindowEx gute Absichten hat.
Wir können PreCreateWindow wie folgt überladen, um den Klassennamen zu ändern:
// TODO: Fügen Sie hier speziellen Code hinzu und/oder rufen Sie die Basisklasse auf //VERIFY(AfxDeferRegisterClass(AFX_WND_REG)); //cs.lpszClass = AfxRegisterWndClass(NULL); 0, sizeof(WNDCLASS)); // defaults wndcls.style = CS_HREDRAW | ; wndcls.hIcon = NULL; // oder ein anderes Symbol laden wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Geben Sie Ihren eigenen Klassennamen für die spätere Verwendung an wndcls.lpszClassName = _T("MyNewClass"); // Neue Klasse registrieren und beenden, wenn sie fehlschlägt if(!AfxRegisterClass(&wndcls)) { TRACE("Class Registration Failedn"); return FALSE; wndcls.lpszClassName; return TRUE; //return CWnd::PreCreateWindow(cs);
Tatsächlich geht es darum, eine registrierte Klassennamenzeichenfolge an CreateWindowEx zu übergeben. Den Kommentaren im obigen Code nach zu urteilen, habe ich auch AfxRegisterWndClass verwendet, eine Methode, die es dem System ermöglicht, Klassennamen zu generieren. CWnd::PreCreateWindow entspricht nicht meinen Wünschen, daher habe ich es auskommentiert. Tatsächlich ist nichts drin, es ist nur ein Urteil. In MFC sind andere abgeleitete Klassen von CWnd nicht so einfach. Meistens ist es jedoch in Ordnung, einfach den Klassennamen zu ändern und diese Methode zu überladen.
Ja, die meisten von ihnen können es. Leider funktioniert diese Methode nicht für Dialog, da sie CWnd::Create nicht verwendet und daher nicht umgangen werden kann.
PreCreateWindow wird aufgerufen. Sie können diese Methode des Dialogfelds überladen. Haltepunkte können nicht unterbrochen werden. Da die Erstellung von CDialog direkt über die API des Systems erfolgen kann und CWnd nicht mit der Übertragung an CReateWindowEx beschäftigt werden muss, können Sie die obige Methode nicht zum Ändern des Klassennamens des Dialogfelds verwenden.
Schauen Sie sich den Erstellungscode an:
Bool CDIALOG :: CREATE (LPCTSTR LPSZTEMPLATENAME, CWND* PPARENTWND) {ASSERT (IS_INTRESOURCE (LPSZTEMPLATENAM) || TemplateName) && m_nid help == 0) m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);#ifdef _DEBUG if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE)) { ASSERT(FALSE); // ungültiger Dialogvorlagenname PostNcDestroy(); // Bereinigung, wenn die Erstellung zu früh fehlschlägt, return FALSE; } #endif //_DEBUG HINSTANCE hInst = AfxFindResourceHandle(HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG); BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst ) ; FreeResource(hTemplate); return bResult;}
Es ist ersichtlich, dass CDialog auf diese Weise im Ressourcenskript erstellt wird. Registrieren Sie diesen Klassennamen, bevor Sie ihn im Dialogfeld erstellen, und warten Sie dann auf Modal Erstellen. Das ist es.
Während dieser Zeit war ich mit anderen Aspekten beschäftigt und habe viel über den MFC-Verpackungsmechanismus vergessen. Zur Auffrischung werde ich den Code nachverfolgen.