关于windows下窗体的ID

关于windows下窗体的ID

Windows平台下每个窗体都有一个ID,窗体创建的时候被设置,主要用来标识子窗体,对不同的窗体,其子窗体的ID可以相同。但同一窗体的不同子窗体必须不同。否则

API如何运行正确:

              HWND GetDlgItem( HWND hDlg,   int nIDDlgItem);

nIDDlgItem: 子窗体的ID

由该API也可以看出,由窗体的ID可得到窗体的句柄,当然还需要其父窗体的句柄作为参数,所以可以进程内不唯一。

MFC的代码(wincore.cpp),标示为红色的参数即为窗体的ID

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)

{

     // 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 = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

              cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

              cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

  

}

由此可见,窗体ID即为CREATESTRUCT.hMenu参数

 

如何得到窗体ID呢?

API LONG lID=GetWindowLong(hWnd, GWL_ID);

设置:

API SetWindowLong(hWnd, GWL_ID,dwNew);

 

看一下MFC是如何分配切分窗体的ID的,看代码(winsplit.cpp

BOOL CSplitterWnd::CreateView(int row, int col,

     CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext)

{

     ()

CWnd* pWnd;

     TRY

     {    //new一个该类的对象,动态创建

         pWnd = (CWnd*)pViewClass->CreateObject();

         if (pWnd == NULL)

              AfxThrowMemoryException();

     }

     CATCH_ALL(e)

     {

         TRACE0("Out of memory creating a splitter pane./n");

         // Note: DELETE_EXCEPTION(e) not required

         return FALSE;

     }

     END_CATCH_ALL

 

     ASSERT_KINDOF(CWnd, pWnd);

     ASSERT(pWnd->m_hWnd == NULL);       // not yet created

 

     DWORD dwStyle = AFX_WS_DEFAULT_VIEW;

     if (afxData.bWin4)

         dwStyle &= ~WS_BORDER;

 

     // Create with the right size (wrong position)

     CRect rect(CPoint(0,0), sizeInit);

     //调用该类的创建函数来创建

     if (!pWnd->Create(NULL, NULL, dwStyle,

         rect, this, IdFromRowCol(row, col), pContext))

     {

         TRACE0("Warning: couldn't create client pane for splitter./n");

              // pWnd will be cleaned up by PostNcDestroy

         return FALSE;

     }

     ASSERT((int)_AfxGetDlgCtrlID(pWnd->m_hWnd) == IdFromRowCol(row, col));

 

     // send initial notification message

     if (bSendInitialUpdate)

         pWnd->SendMessage(WM_INITIALUPDATE);

 

     return TRUE;

}

注意上函数中的IdFromRowCol

int CSplitterWnd::IdFromRowCol(int row, int col) const

{

     ASSERT_VALID(this);

     ASSERT(row >= 0);

     ASSERT(row < m_nRows);

     ASSERT(col >= 0);

     ASSERT(col < m_nCols);

 

     return AFX_IDW_PANE_FIRST + row * 16 + col;

}

至此如何分配ID很明了了,#define AFX_IDW_PANE_FIRST 0xE900,不同切分窗体(CplitterWnd)的子窗体ID可以相同。再一次证明了文章开头的结论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值