Win32 对话框简易封装

CDialogBase.h

cpp 复制代码
#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

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

cpp 复制代码
#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

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

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;
}
相关推荐
45W冲冲冲13 分钟前
WIN10+CMAKE+MinGW+Opencv/C++ 和VScode开发环境搭建
c++·vscode·opencv
春蕾夏荷_72829772518 分钟前
MFC 对话框中显示CScrollView实例
c++·mfc·cscrollview
originalHSL2 小时前
Load-Balanced-Online-OJ(负载均衡式在线OJ)
linux·c++·git·vscode·http·https·json
zhangzhangkeji2 小时前
C++ function 源码分析(5):is_const_v<const 函数> = False ,源码注释及资源
开发语言·c++·stl 库源码
Allen Roson3 小时前
CListCtrl::InsertItem和临界区导致程序卡死
c++·windows·insertitem卡死·clistctrl插入项目·临界区死锁
酒鬼猿3 小时前
C++初阶(十五)--STL--list 的深度解析与全面应用
开发语言·c++
gma9993 小时前
JSONCPP 数据解析与序列化
开发语言·前端·javascript·c++
以卿a3 小时前
C++ 日期计算器的实现(运算符重载)
java·开发语言·c++
2401_840759763 小时前
2062:【例1.3】电影票(http://ybt.ssoier.cn:8088/problem_show.php?pid=2062)
c++
程序员与背包客_CoderZ3 小时前
C++设计模式——Singleton单例模式
c语言·开发语言·c++·单例模式·设计模式