日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何自定义MFC的窗口类名

發布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何自定义MFC的窗口类名 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
作者:滄桑不盡,請尊重原創,轉載注明。 MFC中封裝很多常用的控件,把類名也給封裝了,沒有提供明顯的接口出來,用win api寫窗口程序,第一步就是注冊窗口類

此時類名和標題名是一起注冊的,所以能把標題很好地讓用戶來設定,類名也應該是很簡單的,可惜的是MFC沒有這樣做,原因也許是window name可以不停的改,而類名不能。窗口的類名是有Create來確定的,要在Create前,給窗口選擇一個已經注冊的窗口類名,作為參數窗口Create就ok了,CWnd的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) ||
AfxIsValidAtom(lpszClassName));
ENSURE_ARG(lpszWindowName
== NULL || AfxIsValidString(lpszWindowName));

// allow modification of several common create parameters
CREATESTRUCT cs;
cs.dwExStyle
= dwExStyle;
cs.lpszClass
= lpszClassName;
cs.lpszName
= lpszWindowName;
cs.style
= dwStyle;
cs.x
= x;
cs.y
= y;
cs.cx
= nWidth;
cs.cy
= nHeight;
cs.hwndParent
= hWndParent;
cs.hMenu
= nIDorHMenu;
cs.hInstance
= AfxGetInstanceHandle();
cs.lpCreateParams
= lpParam;

if (!PreCreateWindow(cs))
{
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, "Warning: Window creation failed: GetLastError returns 0x%8.8X/n",
GetLastError());
}
#endif

if (!AfxUnhookWindowCreate())
PostNcDestroy();
// cleanup if CreateWindowEx fails too soon

if (hWnd == NULL)
return FALSE;
ASSERT(hWnd
== m_hWnd); // should have been set in send msg hook
return TRUE;
}

可以看到最后到了::AfxCtxCreateWindowEx,可以很容易地知道這里調用了CreateWindowEx來創建一個窗口

?

在前面有一個PreCreateWindow(cs),而cs經過PreCreateWindow處理后,交給::AfxCtxCreateWindowEx處理

::AfxCtxCreateWindowEx在中轉給CreateWindowEx,cs.lpszClass就是類名,可以清楚了AfxCtxCreateWindowEx的用心良苦


我們可以重載的PreCreateWindow,來修改類名,如下的代碼:

?

// TODO: 在此添加專用代碼和/或調用基類
//VERIFY(AfxDeferRegisterClass(AFX_WND_REG));
//AfxEndDeferRegisterClass(AFX_WND_REG);
//cs.lpszClass = AfxRegisterWndClass(NULL);
WNDCLASS wndcls;

memset(
&wndcls, 0, sizeof(WNDCLASS)); // start with NULL
// defaults

wndcls.style
= CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

//you can specify your own window procedure
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.hInstance
= AfxGetInstanceHandle();
wndcls.hIcon
= NULL; // or load a different icon
wndcls.hCursor =NULL;
wndcls.hbrBackground
= (HBRUSH) (COLOR_WINDOW + 1);
wndcls.lpszMenuName
= NULL;

// Specify your own class name for using FindWindow later
wndcls.lpszClassName = _T("MyNewClass");

// Register the new class and exit if it fails
if(!AfxRegisterClass(&wndcls))
{
TRACE(
"Class Registration Failed/n");
return FALSE;
}


cs.lpszClass
= wndcls.lpszClassName;

return TRUE;
//return CWnd::PreCreateWindow(cs);

?

其實就是為了把一個已經注冊的類名字符串傳給CreateWindowEx,從上面代碼中的注釋中來看,我還用了一種讓系統來生成className的方法AfxRegisterWndClass。CWnd::PreCreateWindow不符合我的心意,注釋掉了,其實里面也沒什么就是判斷而已。而在MFC中CWnd其他派生類就不這么簡單了,不過單純的修改類名,就重載這個方法大多就ok了。

是的,只是大多數可以的,可惜的是這個方法,對于Dialog來說并不行,因為它不用CWnd::Create,也就繞不到

PreCreateWindow上來了,你可以重載對話框的這個方法,斷點,是斷不下來的。因為CDialog的創建可以直接用系統的api來搞,不用再勞駕CWnd來中轉到CReateWindowEx了,所以就不能夠用上述方法來改對話框的類名了。

看下它的創建飛鴿傳書代碼了:

?

BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
ASSERT(IS_INTRESOURCE(lpszTemplateName)
||
AfxIsValidString(lpszTemplateName));

m_lpszTemplateName
= lpszTemplateName; // used for help
if (IS_INTRESOURCE(m_lpszTemplateName) && m_nIDHelp == 0)
m_nIDHelp
= LOWORD((DWORD_PTR)m_lpszTemplateName);

#ifdef _DEBUG
if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE))
{
ASSERT(FALSE);
// invalid dialog template name
PostNcDestroy(); // cleanup if Create fails too soon
return FALSE;
}
#endif //_DEBUG

HINSTANCE hInst
= AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
HRSRC hResource
= ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
HGLOBAL hTemplate
= LoadResource(hInst, hResource);
BOOL bResult
= CreateIndirect(hTemplate, pParentWnd, hInst);
FreeResource(hTemplate);

return bResult;
}

?

?

可以看出來CDialog是靠資源來創建的,可以這樣來來搞的,在資源腳本中定義Class “對話框類名”在對話框domodal或者Create前注冊這個類名,然后等著modal和Create后就可以了。

?

?

這段時間,一直忙一些其他方面了,對MFC封裝機制淡忘了不少,跟蹤下代碼,算是溫習一下了。

總結

以上是生活随笔為你收集整理的如何自定义MFC的窗口类名的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。