O MFC encapsula muitos controles comumente usados e encapsula os nomes das classes sem fornecer uma interface óbvia. Para escrever um programa de janela usando win api, a primeira etapa é registrar a classe de janela.
Neste momento, o nome da classe e o nome do título são registrados juntos, de modo que o título pode ser facilmente definido pelo usuário. O nome da classe também deve ser muito simples. Infelizmente, o MFC não faz isso. pode ser alterado continuamente, mas o nome da classe não. O nome da classe da janela é determinado por Create. Antes de Create, você precisa selecionar um nome de classe de janela registrado para a janela. Basta olhar. em CreateEx. Muito mais claro.
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, dwEstilo, 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 || || lpszClassName )); estilo = dwStyle; ) { PostNcDestroy(); return FALSE } AfxHookWindowCreate(this); HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs. x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);#ifdef _DEBUG if (hWnd == NULL) { TRACE(traceAppMsg, 0, "Aviso: falha na criação da janela: GetLastError retorna 0x%8.8 Xn", GetLastError()); }#endif if (!AfxUnhookWindowCreate()) PostNcDestroy(); // limpeza se CreateWindowEx falhar muito cedo if (hWnd == NULL) return FALSE; ASSERT(hWnd == m_hWnd); // deveria ter sido definido no gancho send msg return TRUE;}
Você pode ver que finalmente chega a::AfxCtxCreateWindowEx. Você pode saber facilmente que CreateWindowEx é chamado aqui para criar uma janela.
Há um PreCreateWindow(cs) na frente e, após cs ser processado por PreCreateWindow, ele é entregue a ::AfxCtxCreateWindowEx para processamento
::AfxCtxCreateWindowEx é transferido para CreateWindowEx. cs.lpszClass é o nome da classe, o que deixa claro que AfxCtxCreateWindowEx tem boas intenções.
Podemos sobrecarregar PreCreateWindow para modificar o nome da classe, como segue:
// TODO: Adicione código especializado aqui e/ou chame a classe base //VERIFY(AfxDeferRegisterClass(AFX_WND_REG)); //AfxEndDeferRegisterClass(AFX_WND_REG); 0, sizeof(WNDCLASS)); // comece com NULL // padrões wndcls.style = CS_HREDRAW | CS_VREDRAW; ; wndcls.hIcon = NULL; // ou carregue um ícone diferente wndcls.hCursor =NULL; wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wndcls.lpszClassName = _T("MyNewClass"); // Registra a nova classe e sai se ela falhar if(!AfxRegisterClass(&wndcls)) { TRACE("Class Registration Failedn"); wndcls.lpszClassName; return TRUE; //retornar CWnd::PreCreateWindow(cs);
Na verdade, é para passar uma string de nome de classe registrada para CreateWindowEx. A julgar pelos comentários no código acima, também usei AfxRegisterWndClass, um método que permite ao sistema gerar className. CWnd::PreCreateWindow não atende aos meus desejos, então comentei. Na verdade, não há nada nele, é apenas um julgamento. No MFC, outras classes derivadas de CWnd não são tão simples. No entanto, simplesmente modificar o nome da classe e sobrecarregar esse método será suficiente.
Sim, a maioria deles pode. Infelizmente, esse método não funciona para o Dialog, porque ele não usa CWnd::Create, portanto não pode ser contornado.
PreCreateWindow está chegando. Você pode sobrecarregar este método da caixa de diálogo. Os pontos de interrupção não podem ser quebrados. Como a criação do CDialog pode ser feita diretamente usando a API do sistema, e não há necessidade de incomodar o CWnd para transferir para o CReateWindowEx, você não pode usar o método acima para alterar o nome da classe da caixa de diálogo.
Dê uma olhada em seu código de criação:
BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd){ ASSERT(IS_INTRESOURCE(lpszTemplateName) || AfxIsValidString(lpszTemplateName)); ) m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);#ifdef _DEBUG if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE)) { ASSERT(FALSE); // nome do modelo de diálogo inválido PostNcDestroy(); } #endif //_DEBUG HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG); HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG = LoadResource(hInst, hResource); ) ; FreeResource(hTemplate); return bResult;}
Pode-se observar que CDialog é criado por recursos. Isso pode ser feito desta forma: Defina a classe "nome da classe de diálogo" no script de recurso antes de domodal ou Criar e aguarde modal e. Crie. É isso.
Durante esse período, estive ocupado com outros aspectos e esqueci muito sobre o mecanismo de empacotamento do MFC. Vou rastrear o código para relembrar.