自定义MessageBox

来源:互联网 发布:集团网络电话交换机 编辑:程序博客网 时间:2024/05/18 22:18

                    自定义MessageBox

#include <wtypes.h>HHOOK g_hMsgBoxHook;void OnModifyMsgBoxOk(HWND hwnd){SetDlgItemText(hwnd, IDOK, "确定按钮");}LRESULT CALLBACK CBTHookProcOk(int nCode, WPARAM wParam, LPARAM lParam){if (nullptr == g_hMsgBoxHook)return 0;if (nCode == HCBT_ACTIVATE){OnModifyMsgBoxOk((HWND)wParam);UnhookWindowsHookEx(g_hMsgBoxHook);g_hMsgBoxHook = nullptr;return 0;}return CallNextHookEx(g_hMsgBoxHook, nCode, wParam, lParam);}int MsgBoxOk(HWND hParent, LPCTSTR pszText,LPCTSTR pszCaption,UINT uType){int ret;g_hMsgBoxHook = SetWindowsHookEx(WH_CBT,CBTHookProcOk,nullptr,GetCurrentThreadId());ret = MessageBox(hParent, pszText, pszCaption, uType);return ret;}void main(){MsgBoxOk(nullptr, "修改确定按钮", "MsgBox", MB_OK);}

hook WH_CBT   拦截MessageBox窗口句柄,从而进行操作,在 OnModifyMsgBoxOk函数里进行操作就行了。缺点:在多线程情况下可能会出现问题。而且不同的窗口样式,需要增加不同的修改函数。

所以 我写了一个基类,解决多线程的问题。子类通过继承基类,可以修改写OnModifyMsgBox来 适合自己的类型。

MsgBoxBase.hpp

/**author: zyb*   \brief  MsgBoxBase*/#pragma once#include <windows.h>#include <xstring>#include <map>class lock{public:lock(){InitializeCriticalSection(&m_cs);}~lock(){DeleteCriticalSection(&m_cs);}void up(){EnterCriticalSection(&m_cs);}void un(){LeaveCriticalSection(&m_cs);}private:CRITICAL_SECTION m_cs;};template<typename _charType>struct MsgBoxT{};template<>struct MsgBoxT<char>{static inline auto c()->decltype(MessageBoxA)*{return MessageBoxA;}};template<>struct MsgBoxT<wchar_t>{static inline auto c()->decltype(MessageBoxW)*{return MessageBoxW;}};template<typename _charType>class MsgBoxBase{public:typedef std::basic_string<_charType, std::char_traits<_charType>, std::allocator<_charType> > str_t;typedef _charType*psz_t;typedef MsgBoxBase<_charType>my_t;typedef my_t*pmy_t;typedef std::map<DWORD, pmy_t > save_t;typedef typename save_t::iteratoriterator_t;public:MsgBoxBase(HWND hParent, psz_t pszText, psz_t pszCaption, UINT uType){m_hParent= hParent;m_strText= pszText;m_strCaption= pszCaption;m_uType= uType;m_hHook= nullptr;}int Show(){int ret;DWORD ThreadId = GetCurrentThreadId();ms_lk.up();ms_ThreadData.insert(std::make_pair(ThreadId, this));ms_lk.un();m_hHook = SetWindowsHookEx(WH_CBT,CBTHookProc,nullptr,ThreadId);ret =MsgBoxT<_charType>::c()(m_hParent, m_strText.c_str(), m_strCaption.c_str(), m_uType);return ret;}protected:virtual void OnModifyMsgBox(HWND hwnd) = 0;private:static LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam){DWORD ThreadId = GetCurrentThreadId();iterator_t ir = ms_ThreadData.find(ThreadId);if (ms_ThreadData.end() == ir)return 0;pmy_t obj = ir->second;if (nCode == HCBT_ACTIVATE){obj->OnModifyMsgBox((HWND)wParam);UnhookWindowsHookEx(obj->m_hHook);obj->m_hHook = nullptr;ms_lk.up();ms_ThreadData.erase(ir);ms_lk.un();return 0;}return CallNextHookEx(obj->m_hHook, nCode, wParam, lParam);}private:static save_tms_ThreadData;static lockms_lk;HWNDm_hParent;str_tm_strText;str_tm_strCaption;UINTm_uType;HHOOKm_hHook;};template<typename _charType>typename MsgBoxBase<_charType>::save_t MsgBoxBase<_charType>::ms_ThreadData;template<typename _charType>lock MsgBoxBase<_charType>::ms_lk;


test.cpp

#include <wtypes.h>#include "MsgBoxBase.hpp"class MsgBox : public MsgBoxBase<char>{public:MsgBox(HWND hParent, char* pszText, char* pszCaption, UINT uType) :MsgBoxBase(hParent, pszText, pszCaption, uType){}protected:virtual void OnModifyMsgBox(HWND hWnd) override{SetDlgItemText(hWnd, IDOK, "确定按钮");}};DWORD WINAPI ThreadProc(LPVOID lpThreadParameter){MsgBox mb(nullptr, "修改确定按钮", "MsgBox", MB_OK);mb.Show();return 0;}void main(){HANDLE hThreads[20];for (int i = 0; i < 20; i++){hThreads[i] = CreateThread(nullptr, 0, ThreadProc, 0, 0, 0);}WaitForMultipleObjects(20, hThreads, true, INFINITE);for (int i = 0; i < 20; i++){CloseHandle(hThreads[i]);}}


原创粉丝点击