对话框简易封装(Win32, C++)

博客包含CDialogBase.h、CDialogBase.cpp等文件,涉及Win32和C++相关内容,还进行了测试,有CDialogTest.h、CDialogTest.cpp及main.cpp等代码文件,聚焦于Win32窗口相关开发测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CDialogBase.h

#pragma once

#include <Windows.h>
#include <tchar.h>
#include <string>

#pragma warning(disable:4100)

#ifdef UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

class CDialogBase;

typedef LRESULT(CDialogBase::* pMessageFn)(WPARAM wParam, LPARAM lParam);
typedef LRESULT(CDialogBase::* pCommandFn)(WORD wNotify, WORD wID, HWND hWnd);
typedef LRESULT(CDialogBase::* pNotifyFn)(WORD wID, LPNMHDR pNmhdr);

struct DLG_WND_MSGMAP_ENTRY
{
    union
    {
        pMessageFn m_pFnMessage;
        pCommandFn m_pFnCommand;
        pNotifyFn m_pFnNotify;

    }m_pFunc;               //要调用的例程(或特殊值)
    UINT m_nMessage;        //Windows消息
    UINT m_nCode;           //控件码或 or WM_NOTIFY code
    UINT m_nID;             //控件ID (Windows消息则为0)
    UINT m_nLastID;         //用于指定控件 ID 范围的条目

    DLG_WND_MSGMAP_ENTRY()
        :
        m_nMessage(0),
        m_nCode(0),
        m_nID(0),
        m_nLastID(0)
    {
        m_pFunc.m_pFnMessage = nullptr;
    }

    DLG_WND_MSGMAP_ENTRY(UINT uMsg, pMessageFn pfn)
        :
        m_nMessage(uMsg),
        m_nCode(0),
        m_nID(0),
        m_nLastID(0)
    {
        m_pFunc.m_pFnMessage = pfn;
    }

    DLG_WND_MSGMAP_ENTRY(UINT uMsg, UINT id, pCommandFn pfn)
        :
        m_nMessage(uMsg),
        m_nCode(0),
        m_nID(id),
        m_nLastID(0)
    {
        m_pFunc.m_pFnCommand = pfn;
    }

    DLG_WND_MSGMAP_ENTRY(UINT uMsg, UINT id, UINT idLast, pCommandFn pfn)
        :
        m_nMessage(uMsg),
        m_nCode(0),
        m_nID(id),
        m_nLastID(idLast)
    {
        m_pFunc.m_pFnCommand = pfn;
    }

    DLG_WND_MSGMAP_ENTRY(UINT uMsg, UINT wNotifyCode, UINT id, UINT idLast, pNotifyFn pfn)
        :
        m_nMessage(uMsg),
        m_nCode(wNotifyCode),
        m_nID(id),
        m_nLastID(idLast)
    {
        m_pFunc.m_pFnNotify = pfn;
    }
};

struct DLG_WND_MSGMAP
{
    const DLG_WND_MSGMAP* (*pfnGetBaseMap)();
    const DLG_WND_MSGMAP_ENTRY* lpEntries;
};

#ifndef dlg_msg
#define dlg_msg
#endif

#ifndef dlg_command
#define dlg_command
#endif

#ifndef dlg_notify
#define dlg_notify
#endif

#define DECLARE_DLG_MESSAGE_MAP()                                   \
protected:                                                      \
static const DLG_WND_MSGMAP* GetThisMessageMap();                   \
virtual const DLG_WND_MSGMAP* GetMessageMap() const;                \
                                                                
#define BEGIN_DLG_MESSAGE_MAP(theClass, baseClass)                  \
const DLG_WND_MSGMAP* theClass::GetMessageMap() const               \
{                                                               \
    return GetThisMessageMap();                                 \
}                                                               \
const DLG_WND_MSGMAP* theClass::GetThisMessageMap()                 \
{                                                               \
    typedef baseClass TheBaseClass;					            \
static const DLG_WND_MSGMAP_ENTRY _messageEntries[] =               \
{                                                               \

#define ON_DLG_MESSAGE(message, memberFxn)                          \
DLG_WND_MSGMAP_ENTRY(message, static_cast< LRESULT (CDialogBase::*)(WPARAM, LPARAM) >(memberFxn)),

#define ON_DLG_COMMAND(_id, memberFxn)                          \
DLG_WND_MSGMAP_ENTRY(WM_COMMAND, _id, static_cast< LRESULT (CDialogBase::*)(WORD wNotify, WORD wID, HWND hWnd) >(memberFxn)),

#define ON_DLG_COMMAND_RANGE(_id, _idLast, memberFxn)                          \
DLG_WND_MSGMAP_ENTRY(WM_COMMAND, _id, _idLast, static_cast< LRESULT (CDialogBase::*)(WORD wNotify, WORD wID, HWND hWnd) >(memberFxn)),

#define ON_DLG_NOTIFY(_wNotifycode, _id, memberFxn)                          \
DLG_WND_MSGMAP_ENTRY(WM_NOTIFY, (UINT)_wNotifycode, _id, _id,  static_cast< LRESULT (CDialogBase::*)(WORD wID, LPNMHDR pNmhdr) >(memberFxn)),

#define ON_DLG_NOTIFY_RANGE(_wNotifycode, _id, _idLast, memberFxn)                          \
DLG_WND_MSGMAP_ENTRY(WM_NOTIFY, (UINT)_wNotifycode, _id, _idLast,  static_cast< LRESULT (CDialogBase::*)(WORD wID, LPNMHDR pNmhdr) >(memberFxn)),

#define END_DLG_MESSAGE_MAP()  DLG_WND_MSGMAP_ENTRY(0, NULL) }; \
static const DLG_WND_MSGMAP messageMap =                        \
{&TheBaseClass::GetThisMessageMap , &_messageEntries[0] };      \
    return &messageMap;                                         \
}                                                               \

#define DECLARE_DLG_BASE_MESSAGE_MAP()                          \
protected:                                                      \
static const DLG_WND_MSGMAP* GetThisMessageMap();               \
virtual const DLG_WND_MSGMAP* GetMessageMap() const;            \
static const DLG_WND_MSGMAP* GetBaseMessageMap();               \

#define BEGIN_DLG_BASE_MESSAGE_MAP(theClass)                    \
typedef theClass TheThisClass;					                \
const DLG_WND_MSGMAP* TheThisClass::GetMessageMap() const       \
{                                                               \
    return GetThisMessageMap();                                 \
}                                                               \
const DLG_WND_MSGMAP* TheThisClass::GetBaseMessageMap()         \
{                                                               \
    return NULL;                                                \
}                                                               \
const DLG_WND_MSGMAP* TheThisClass::GetThisMessageMap()         \
{                                                               \
static const DLG_WND_MSGMAP_ENTRY _messageEntries[] =           \
{                                                               \

#define END_DLG_BASE_MESSAGE_MAP()  DLG_WND_MSGMAP_ENTRY(0, nullptr) };    \
static const DLG_WND_MSGMAP messageMap =                        \
{&TheThisClass::GetBaseMessageMap, &_messageEntries[0] };       \
return &messageMap;                                             \
}                                                               \

class CDialogBase
{
public:
    CDialogBase();
    CDialogBase(const CDialogBase& r) = delete;
    CDialogBase& operator = (const CDialogBase& r) = delete;
    ~CDialogBase();

    INT_PTR DoModal(HWND hWndParent, bool bCenter = true);
    INT_PTR DoModal(UINT resourceID, HWND hWndParent, bool bCenter = true);
    INT_PTR DoModalEx(UINT resourceID, HWND hWndParent, BOOL isShow = TRUE, bool bCenter = true);
    HWND DoDialog(UINT resourceID, HWND hWndParent, BOOL isShow = TRUE, bool bCenter = true);

public:
    dlg_msg LRESULT OnClose(WPARAM wParam, LPARAM lParam);

    dlg_msg LRESULT OnMsgTest(WPARAM wParam, LPARAM lParam);
    dlg_command LRESULT OnCommandTest(WORD wNotify, WORD wID, HWND hWnd);
    dlg_notify LRESULT OnNotifyTest(WORD wID, LPNMHDR pNmhdr);

public:

    //设置对话框资源
    void SetResourceID(UINT resourceID);

    //显示窗口
    void ShowWindow(int cmdShow = SW_SHOW);

    //检查窗口是否显示
    bool IsVisiable() const;

    //移动窗口到父窗口中心
    void MoveToCenter(HWND hParent);

    //修改菜单文本
    void ModifyMenuText(HMENU hMnu, UINT uPosition, LPCTSTR lpNewItem, BOOL fByPos = TRUE);

    //修改菜单文本为资源字符串
    void ModifyMenuText(HMENU hMnu, UINT uPosition, UINT resourceID, BOOL fByPos = TRUE);

    //修改菜单状态
    void ModifyMenuState(HMENU hMnu, UINT uPosition, UINT fState = MFS_ENABLED, BOOL fByPos = TRUE);

    //获取窗口句柄
    HWND GetWndHandle() const;

    //结束对话框
    bool EndDialog(INT_PTR nResult);

    //消息
    bool PostMessage(UINT uMsg, WPARAM wParam, LPARAM lParam = 0);
    LRESULT SendMessage(UINT uMsg, WPARAM wParam, LPARAM lParam = 0);
    bool PostCommand(WORD wID, WORD wNotify = 0, LPARAM lParam = 0);
    LRESULT SendCommand(WORD wID, WORD wNotify = 0, LPARAM lParam = 0);

    //加载资源字符串
    _tstring LoadString(UINT resourceID);

    //获取子项文本
    _tstring GetItemString(DWORD dwID);

    //设置子项文本
    void SetItemString(DWORD dwID, const _tstring& strText);

    //检查子项按钮是否勾选
    bool IsButtonChecked(int nIDButton) const;

    //勾选子项按钮
    bool CheckButton(int nIDButton, bool bCheck = true);

    //获取子项窗口句柄
    HWND GetItem(DWORD dwID) const;

    //检查菜单项是否勾选
    bool IsMenuItemChecked(HMENU hMenu, UINT uId, bool fByPosition = false);

    //勾选菜单项
    void CheckMenuItem(HMENU hMenu, UINT uId, bool bCheck, bool fByPosition = false);

    //检查菜单项是否启用
    bool IsMenuItemEnable(HMENU hMenu, UINT uId, bool fByPosition = false);

    //启用菜单项
    void EnableMenuItem(HMENU hMenu, UINT uId, bool bCheck, bool fByPosition = false);

    //获取菜单项文本
    _tstring GetMenuItemString(HMENU hMenu, UINT uId, bool bCheck, bool fByPosition = false);

    //设置菜单项文本
    bool SetMenuItemString(HMENU hMenu, UINT uId, const _tstring strText, bool fByPosition = false);

    operator HWND() const
    {
        return m_hWnd;
    }


protected:

    //假模态对话框
    dlg_msg LRESULT DoFakeModal(UINT resourceID, HWND hWndParent, BOOL isShow = TRUE);
    static INT_PTR WINAPI DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);

public:

    virtual BOOL PreTranslateMessage(LPMSG pMsg);
    virtual BOOL DialogMessage(LPMSG pMsg);

protected:
    HWND m_hWnd;
    UINT m_resID;
    BOOL m_bModel;
    BOOL m_bFakeModel;
    BOOL m_bCenter;
    DECLARE_DLG_BASE_MESSAGE_MAP()
};

CDialogBase.cpp

#include "CDialogBase.h"
#include <Windows.h>
#include <strsafe.h>

#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BEGIN_DLG_BASE_MESSAGE_MAP(CDialogBase)
    ON_DLG_MESSAGE(WM_CLOSE, &CDialogBase::OnClose)

    ON_DLG_MESSAGE(0/*消息*/, &CDialogBase::OnMsgTest)
    ON_DLG_COMMAND(0/*控件ID*/, &CDialogBase::OnCommandTest)
    ON_DLG_NOTIFY(0/*通知码*/, 0/*控件ID*/, &CDialogBase::OnNotifyTest)
    ON_DLG_COMMAND_RANGE(0/*控件ID起始*/, 0/*控件ID结束*/, &CDialogBase::OnCommandTest)
    ON_DLG_NOTIFY_RANGE(0/*通知码*/, 0/*控件ID起始*/, 0/*控件ID结束*/, &CDialogBase::OnNotifyTest)
END_DLG_BASE_MESSAGE_MAP()

CDialogBase::CDialogBase()
    :
    m_hWnd(NULL),
    m_resID(0),
    m_bModel(FALSE),
    m_bFakeModel(FALSE),
    m_bCenter(FALSE)
{

}

CDialogBase::~CDialogBase()
{
    if (NULL != m_hWnd)
    {
        ::DestroyWindow(m_hWnd);
    }
}

HWND CDialogBase::DoDialog(UINT resourceID, HWND hWndParent, BOOL isShow, bool bCenter/* = true*/)
{
    m_bCenter = bCenter;
    m_bModel = FALSE;
    m_resID = resourceID;
    HWND hWnd = ::CreateDialogParam(GetModuleHandle(NULL), MAKEINTRESOURCE(resourceID), hWndParent, DialogProc, (LPARAM)this);
    m_hWnd = hWnd;

    if (isShow)
    {
        ::ShowWindow(m_hWnd, SW_SHOW);
    }

    return m_hWnd;
}

INT_PTR CDialogBase::DoModalEx(UINT resourceID, HWND hWndParent, BOOL isShow, bool bCenter/* = true*/)
{
    m_bCenter = bCenter;
    m_bModel = FALSE;
    return DoFakeModal(resourceID, hWndParent, isShow);
}

INT_PTR CDialogBase::DoModal(HWND hWndParent, bool bCenter/* = true*/)
{
    m_bCenter = bCenter;
    m_bModel = TRUE;
    return ::DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(m_resID), hWndParent, DialogProc, (LPARAM)this);
}

INT_PTR CDialogBase::DoModal(UINT resourceID, HWND hWndParent, bool bCenter/* = true*/)
{
    m_bCenter = bCenter;
    m_resID = resourceID;
    m_bModel = TRUE;
    return ::DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(m_resID), hWndParent, DialogProc, (LPARAM)this);
}

BOOL CDialogBase::DialogMessage(LPMSG pMsg)
{
    return ::IsDialogMessage(m_hWnd, pMsg);
}

BOOL CDialogBase::PreTranslateMessage(LPMSG pMsg)
{
    return FALSE;
}

bool CDialogBase::EndDialog(INT_PTR nResult)
{
    if (NULL == m_hWnd)
    {
        return false;
    }

    if (m_bFakeModel)
    {
        //启用父窗口
        HWND hParent = ::GetParent(m_hWnd);
        if (hParent)
        {
            ::EnableWindow(hParent, TRUE);
        }

        // 投递 WM_QUIT 消息退出消息环 (窗口句柄指定为NULL时, 
        // 该函数的行为类似于对 PostThreadMessage 的调用, 
        // 其中 dwThreadId 参数设置为当前线程的标识符。)
        ::PostMessage(NULL, WM_QUIT, nResult, 0);
    }

    if (m_bModel)
    {
        ::EndDialog(m_hWnd, nResult);
        m_hWnd = NULL;
    }
    else
    {
        ::DestroyWindow(m_hWnd);
        m_hWnd = NULL;
    }

    return TRUE;
}

LRESULT CDialogBase::OnClose(WPARAM wParam, LPARAM lParam)
{
    return EndDialog(wParam);
}

LRESULT CDialogBase::DoFakeModal(UINT resourceID, HWND hWndParent, BOOL isShow)
{
    m_bModel = FALSE;
    m_resID = resourceID;
    m_bFakeModel = TRUE;

    m_hWnd = ::CreateDialogParam(GetModuleHandle(NULL), MAKEINTRESOURCE(resourceID), hWndParent, DialogProc, (LPARAM)this);
    if (NULL == m_hWnd)
    {
        return -1;
    }

    if (isShow)
    {
        ::ShowWindow(m_hWnd, SW_SHOW);
    }

    //禁用父窗口
    HWND hParent = GetParent(m_hWnd);
    if (hParent)
    {
        ::EnableWindow(hParent, FALSE);
    }

    MSG msg = { 0 };
    BOOL bRet = FALSE;

    //如果 hWnd 为 NULL, 则 GetMessage 将检索属于当前线程的任何窗口的消息,以及当前线程的消息队列上 hwnd 值为 NULL 的任何消息,
    //因此,如果 hWnd 为 NULL,则同时处理窗口消息和线程消息。
    //如果 hWnd 为 - 1,则 GetMessage 仅检索当前线程的消息队列中 hwnd 值为 NULL 的消息,
    //即当 hWnd 参数为 NULL 或 PostThreadMessage 时,PostMessage 发布的线程消息。

    while (0 != (bRet = GetMessage(&msg, NULL, 0, 0)))
    {
        if (-1 == bRet)
        {
            break;
        }

        //类捕获消息处理与对话框 TAB 按键处理
        if (PreTranslateMessage(&msg))
        {
            continue;
        }

        //类捕获消息处理与对话框 TAB 按键处理
        if (DialogMessage(&msg))
        {
            continue;
        }

        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    return msg.wParam;
}

INT_PTR WINAPI CDialogBase::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CDialogBase* pThis = reinterpret_cast<CDialogBase*>(GetProp(hWnd, _T("this")));

    if (pThis)
    {
        return pThis->DialogProc(uMsg, wParam, lParam);
    }

    if (WM_INITDIALOG == uMsg)
    {
        pThis = reinterpret_cast<CDialogBase*>(lParam);
        pThis->m_hWnd = hWnd;
        SetProp(hWnd, _T("this"), pThis);
        pThis->DialogProc(uMsg, wParam, lParam);

        if (pThis->m_bCenter)
        {
            pThis->MoveToCenter(::GetParent(hWnd));
        }

        return (INT_PTR)TRUE;
    }

    return (INT_PTR)FALSE;
}

INT_PTR CDialogBase::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    const DLG_WND_MSGMAP* pEntry = GetMessageMap();
    LRESULT lpResult = NULL;

    while (pEntry)
    {
        const DLG_WND_MSGMAP_ENTRY* lpEntries = pEntry->lpEntries;
        while (lpEntries->m_pFunc.m_pFnMessage)
        {
            if (uMsg == lpEntries->m_nMessage)
            {
                //处理 WM_COMMAND 消息
                if (WM_COMMAND == uMsg)
                {
                    //消息源   HIWORD(wParam)      LOWORD(wParam)     lParam 
                    //菜单     0                   菜单ID             0
                    //快捷键   1                   快捷键ID           0
                    //控件     控件定义的通知码    控件ID             控件窗口句柄
                    WORD wNotify = HIWORD(wParam);
                    WORD wID = LOWORD(wParam);
                    HWND hWnd = (HWND)lParam;

                    //ID范围检测
                    if (wID >= lpEntries->m_nID && wID <= lpEntries->m_nID)
                    {
                        lpResult = (this->*lpEntries->m_pFunc.m_pFnCommand)(wNotify, wID, hWnd);
                        break;
                    }
                }
                else if (WM_NOTIFY == uMsg)
                {
                    WORD wID = (WORD)wParam;                  //发送消息的公共控件的标识符。 不保证此标识符是唯一的。
                    LPNMHDR pNmhdr = (LPNMHDR)lParam;  //指向包含通知代码和其他信息的 NMHDR 结构的指针

                    if (pNmhdr->code == lpEntries->m_nCode && pNmhdr->idFrom >= lpEntries->m_nID && pNmhdr->idFrom <= lpEntries->m_nID)
                    {
                        lpResult = (this->*lpEntries->m_pFunc.m_pFnNotify)(wID, pNmhdr);
                        break;
                    }
                }
                else
                {
                    lpResult = (this->*lpEntries->m_pFunc.m_pFnMessage)(wParam, lParam);
                    break;
                }
            }

            lpEntries++;
        }

        //子类处理了则返回
        if (lpResult)
        {
            ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, lpResult);
            return lpResult;
        }

        //获取基类的消息映射
        pEntry = pEntry->pfnGetBaseMap();
    }

    return FALSE;
}

void CDialogBase::SetResourceID(UINT resourceID)
{
    m_resID = resourceID;
}

void CDialogBase::ShowWindow(int cmdShow)
{
    ::ShowWindow(m_hWnd, cmdShow);
}

bool CDialogBase::IsVisiable() const
{
    return ::IsWindowVisible(m_hWnd);
}

void CDialogBase::MoveToCenter(HWND hParent)
{
    RECT rectParent = { 0 };
    RECT rectChild = { 0 };
    RECT rectWork = { 0 };
    LONG dwParentW = 0;
    LONG dwParentH = 0;
    LONG dwChildW = 0;
    LONG dwChildH = 0;
    LONG dwChildX = 0;
    LONG dwChildY = 0;
    ::GetWindowRect(m_hWnd, &rectChild);

    SystemParametersInfo(SPI_GETWORKAREA, 0, &rectWork, 0);

    if (NULL == hParent)
    {
        hParent = ::GetDesktopWindow();
    }

    ::GetWindowRect(hParent, &rectParent);

    dwParentW = rectParent.right - rectParent.left;
    dwParentH = rectParent.bottom - rectParent.top;
    dwChildW = rectChild.right - rectChild.left;
    dwChildH = rectChild.bottom - rectChild.top;
    dwChildX = rectParent.left + (dwParentW - dwChildW) / 2;
    dwChildY = rectParent.top + (dwParentH - dwChildH) / 2;

    if (dwChildX < 0)
    {
        dwChildX = 0;
    }

    if (dwChildY < 0)
    {
        dwChildY = 0;
    }

    if ((dwChildX + dwChildW) > rectWork.right)
    {
        dwChildX = rectWork.right - dwChildW;
    }

    if ((dwChildY + dwChildH) > rectWork.bottom)
    {
        dwChildY = rectWork.bottom - dwChildH;
    }

    ::MoveWindow(
        m_hWnd, 
        dwChildX,
        dwChildY,
        dwChildW, 
        dwChildH, 
        TRUE
    );
}

_tstring CDialogBase::LoadString(UINT uID)
{
    _tstring strResult;
    LPTSTR lpData = nullptr;

    do
    {
        //获取资源长度
        LPCTSTR lpCStr = nullptr;
        int nLength = ::LoadString(GetModuleHandle(NULL), uID, (LPWSTR)&lpCStr, 0);
        if (0 == nLength)
        {
            break;
        }

        //分配字符串缓冲
        nLength += 1;
        lpData = (LPTSTR)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(TCHAR));
        if (NULL == lpData)
        {
            break;
        }

        //拷贝
        ::StringCchCopy(lpData, nLength, lpCStr);
        strResult = lpData;

    } while (false);

    if (NULL != lpData)
    {
        ::HeapFree(::GetProcessHeap(), 0, lpData);
    }

    return strResult;
}

_tstring CDialogBase::GetItemString(DWORD dwID)
{
    _tstring strResult;
    LPTSTR lpData = nullptr;

    do
    {
        DWORD dwLength = GetWindowTextLength(GetDlgItem(m_hWnd, dwID));
        if (0 == dwLength)
        {
            break;
        }

        dwLength += 1;
        lpData = (LPTSTR)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(TCHAR));
        if (NULL == lpData)
        {
            break;
        }

        ::GetDlgItemText(m_hWnd, dwID, lpData, dwLength);
        strResult = lpData;

    } while (false);


    if (NULL != lpData)
    {
        ::HeapFree(::GetProcessHeap(), 0, lpData);
    }

    return strResult;
}

bool CDialogBase::IsButtonChecked(int nIDButton) const
{
    return BST_CHECKED == ::IsDlgButtonChecked(m_hWnd, nIDButton);
}

bool CDialogBase::CheckButton(int nIDButton, bool bCheck/* = true*/)
{
    return ::CheckDlgButton(m_hWnd, nIDButton, bCheck ? BST_CHECKED : BST_UNCHECKED);
}

HWND CDialogBase::GetItem(DWORD dwID) const
{
    return ::GetDlgItem(m_hWnd, dwID);
}

bool CDialogBase::IsMenuItemChecked(HMENU hMenu, UINT uId, bool fByPosition/* = false*/)
{
    MENUITEMINFO mii = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_STATE;
    ::GetMenuItemInfo(hMenu, uId, fByPosition, &mii);

    return mii.fState & MF_CHECKED;
}

void CDialogBase::CheckMenuItem(HMENU hMenu, UINT uId, bool bCheck, bool fByPosition/* = false*/)
{
    MENUITEMINFO mii = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_STATE;
    ::GetMenuItemInfo(hMenu, uId, fByPosition, &mii);

    if (bCheck)
    {
        mii.fState |= MF_CHECKED;
    }
    else
    {

        mii.fState &= ~MF_CHECKED;
    }

    ::SetMenuItemInfo(hMenu, uId, fByPosition, &mii);
}

bool CDialogBase::IsMenuItemEnable(HMENU hMenu, UINT uId, bool fByPosition/* = false*/)
{
    MENUITEMINFO mii = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_STATE;
    ::GetMenuItemInfo(hMenu, uId, fByPosition, &mii);

    return (mii.fState & MFS_DISABLED) ? false : true;
}

void CDialogBase::EnableMenuItem(HMENU hMenu, UINT uId, bool bCheck, bool fByPosition/* = false*/)
{
    MENUITEMINFO mii = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_STATE;
    ::GetMenuItemInfo(hMenu, uId, fByPosition, &mii);

    if (bCheck)
    {
        mii.fState &= ~MFS_DISABLED;
    }
    else
    {

        mii.fState |= MFS_DISABLED;
    }

    ::SetMenuItemInfo(hMenu, uId, fByPosition, &mii);
}

_tstring CDialogBase::GetMenuItemString(HMENU hMenu, UINT uId, bool bCheck, bool fByPosition/* = false*/)
{
    MENUITEMINFO mii = { 0 };
    TCHAR szBuf[MAX_PATH] = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_TYPE | MIIM_DATA;
    mii.dwTypeData = szBuf;
    mii.cch = _countof(szBuf);
    ::GetMenuItemInfo(hMenu, uId, fByPosition, &mii);

    if (nullptr == mii.dwTypeData)
    {
        return _tstring();
    }

    return mii.dwTypeData;
}

bool CDialogBase::SetMenuItemString(HMENU hMenu, UINT uId, const _tstring strText, bool fByPosition/* = false*/)
{
    MENUITEMINFO mii = { 0 };
    TCHAR szBuf[MAX_PATH] = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_TYPE | MIIM_DATA;
    mii.dwTypeData = szBuf;
    mii.cch = _countof(szBuf);
    ::GetMenuItemInfo(hMenu, uId, fByPosition, &mii);
    ::StringCchPrintf(szBuf, _countof(szBuf), strText.c_str());
    return ::SetMenuItemInfo(hMenu, uId, fByPosition, &mii);
}

void CDialogBase::SetItemString(DWORD dwID, const _tstring& strText)
{
    ::SetDlgItemText(m_hWnd, dwID, strText.c_str());
}

VOID CDialogBase::ModifyMenuText(HMENU hMnu, UINT uPosition, LPCTSTR lpNewItem, BOOL fByPos)
{
    MENUITEMINFO mii = { 0 };
    TCHAR szBuf[MAX_PATH] = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_TYPE | MIIM_DATA;
    mii.fType = MFT_STRING;
    mii.dwTypeData = szBuf;
    mii.cch = _countof(szBuf);
    ::GetMenuItemInfo(hMnu, uPosition, fByPos, &mii);
    ::StringCchCopy(szBuf, _countof(szBuf), lpNewItem);
    ::SetMenuItemInfo(hMnu, uPosition, fByPos, &mii);
}

VOID CDialogBase::ModifyMenuText(HMENU hMnu, UINT uPosition, UINT resourceID, BOOL fByPos)
{
    ModifyMenuText(hMnu, uPosition, LoadString(resourceID).c_str(), fByPos);
}

VOID CDialogBase::ModifyMenuState(HMENU hMnu, UINT uPosition, UINT fState/* = MFS_ENABLED*/, BOOL fByPos/* = TRUE*/)
{
    MENUITEMINFO mii = { 0 };
    TCHAR szBuf[MAX_PATH] = { 0 };
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_DATA;
    mii.fType = MFT_STRING;
    mii.dwTypeData = szBuf;
    mii.cch = _countof(szBuf);
    ::GetMenuItemInfo(hMnu, uPosition, fByPos, &mii);
    mii.fState = fState;
    ::SetMenuItemInfo(hMnu, uPosition, fByPos, &mii);
}

HWND CDialogBase::GetWndHandle() const
{
    if (::IsWindow(m_hWnd))
    {
        return m_hWnd;
    }

    return NULL;
}

bool CDialogBase::PostMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return ::PostMessage(m_hWnd, uMsg, wParam, lParam);
}

LRESULT CDialogBase::SendMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return ::SendMessage(m_hWnd, uMsg, wParam, lParam);
}

bool CDialogBase::PostCommand(WORD wID, WORD wNotify, LPARAM lParam/* = 0*/)
{
    return ::PostMessage(m_hWnd, WM_COMMAND, MAKEWPARAM(wID, wNotify), lParam);
}

LRESULT CDialogBase::SendCommand(WORD wID, WORD wNotify, LPARAM lParam/* = 0*/)
{
    return ::SendMessage(m_hWnd, WM_COMMAND, MAKEWPARAM(wID, wNotify), lParam);
}

LRESULT CDialogBase::OnMsgTest(WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

LRESULT CDialogBase::OnCommandTest(WORD wNotify, WORD wID, HWND hWnd)
{
    return TRUE;
}

LRESULT CDialogBase::OnNotifyTest(WORD wID, LPNMHDR pNmhdr)
{
    return TRUE;
}

测试

CDialogTest.h

#pragma once
#include "CWindow/CDialogBase.h"

class CDialogTest :
	public CDialogBase
{
public:


protected:

    dlg_msg LRESULT OnClose(WPARAM wParam, LPARAM lParam);
    dlg_command LRESULT OnOK(WORD wNotify, WORD wID, HWND hWnd);
    dlg_command LRESULT OnCancel(WORD wNotify, WORD wID, HWND hWnd);
    dlg_command LRESULT OnFileExit(WORD wNotify, WORD wID, HWND hWnd);
    dlg_command LRESULT OnSettingTopmost(WORD wNotify, WORD wID, HWND hWnd);
    dlg_command LRESULT OnHelpAbout(WORD wNotify, WORD wID, HWND hWnd);

private:

	DECLARE_DLG_MESSAGE_MAP()
};

CDialogTest.cpp

#include "CDialogTest.h"
#include <Windows.h>
#include <strsafe.h>
#include "resource.h"

BEGIN_DLG_MESSAGE_MAP(CDialogTest, CDialogBase)
    ON_DLG_MESSAGE(WM_CLOSE, &CDialogTest::OnClose)

    ON_DLG_COMMAND(IDOK, &CDialogTest::OnOK)
    ON_DLG_COMMAND(IDCANCEL, &CDialogTest::OnCancel)
    ON_DLG_COMMAND(ID_FILE_EXIT, &CDialogTest::OnFileExit)
    ON_DLG_COMMAND(ID_SETTINGS_TOPMOST, &CDialogTest::OnSettingTopmost)
    ON_DLG_COMMAND(ID_HELP_ABOUT, &CDialogTest::OnHelpAbout)
END_DLG_MESSAGE_MAP()

LRESULT CDialogTest::OnClose(WPARAM wParam, LPARAM lParam)
{
    return (LRESULT)FALSE;
}

LRESULT CDialogTest::OnOK(WORD wNotify, WORD wID, HWND hWnd)
{
    EndDialog(IDOK);
    return (LRESULT)TRUE;
}

LRESULT CDialogTest::OnCancel(WORD wNotify, WORD wID, HWND hWnd)
{
    EndDialog(IDCANCEL);
    return (LRESULT)TRUE;
}

LRESULT CDialogTest::OnFileExit(WORD wNotify, WORD wID, HWND hWnd)
{
    PostMessage(WM_CLOSE, 0, 0);
    return (LRESULT)TRUE;
}

LRESULT CDialogTest::OnSettingTopmost(WORD wNotify, WORD wID, HWND hWnd)
{
    bool bTopmost = IsMenuItemChecked(GetMenu(m_hWnd), wID);
    CheckMenuItem(GetMenu(m_hWnd), wID, !bTopmost);
    SetWindowPos(m_hWnd, !bTopmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    return (LRESULT)TRUE;
}

LRESULT CDialogTest::OnHelpAbout(WORD wNotify, WORD wID, HWND hWnd)
{
    return (LRESULT)TRUE;
}

main.cpp

#include "CDialogTest.h"
#include <windows.h>
#include "resource.h"

int APIENTRY WinMain(
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nShowCmd)
{
    UNREFERENCED_PARAMETER(hInstance);
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    UNREFERENCED_PARAMETER(nShowCmd);

    CDialogTest dlg;
    dlg.DoModalEx(IDD_DIALOG_TEST, nullptr);
    return 0;
}

 

264ad3ee91a14d4dbc48d3c093d8fdce.png

 

 

使用C++代码封装win32操作, 与MFC相似,对于学习SDK与C++是巨好的参考 Tutorials Menu of tutorials Tutorial 1: The Simplest Window Tutorial 2: Using Classes and Inheritance Tutorial 3: Using Messages to Create a Scribble Window Tutorial 4: Repainting the Window Tutorial 5: Wrapping a Frame around our Scribble Window Tutorial 6: Customising Window Creation Tutorial 7: Customising the Toolbar Tutorial 8: Loading and Saving Files Tutorial 9: Printing Tutorial 10: Finishing Touches Tutorial 1: The Simplest Window The following code uses Win32++ to create a window. This is all the code you need (in combination with Win32++) to create and display a simple window. Note that in order to add the Win32++ code to our program, we use an #include statement as shown below. #include "../Win32++/Wincore.h" INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPTSTR, int) { //Start Win32++ CWinApp MyApp; //Create a CWnd object CWnd MyWindow; //Create (and display) the window MyWindow.Create(); //Run the application return MyApp.Run(); } This program has four key steps: Start Win32++. We do this here by creating a CWinApp object called MyApp. Create a CWnd object called MyWindow. Create a default window by calling the Create function. Start the message loop, by calling the Run function. If you compile and run this program, you'll find that the application doesn't end when the window is closed. This is behaviour is normal. An illustration of how to use messages to control the windows behaviour (including closing the application) will be left until tutorial 3.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值