Win32SDK实现自定义消息框(亦可用来做应用窗口框架)
使用简单,static控件实现同时支持水平居中对齐、垂直居中对齐和自动换行。
class MessageWindow { public: MessageWindow() { // InitCommonControlsEx() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. INITCOMMONCONTROLSEX InitCtrls = { 0 }; InitCtrls.dwSize = sizeof(InitCtrls); // Set this to include all the common control classes you want to use // in your application. InitCtrls.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_BAR_CLASSES | ICC_TAB_CLASSES | ICC_UPDOWN_CLASS | ICC_PROGRESS_CLASS | ICC_HOTKEY_CLASS | ICC_ANIMATE_CLASS | ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_INTERNET_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS | ICC_STANDARD_CLASSES | ICC_LINK_CLASS; InitCommonControlsEx(&InitCtrls); m_hGlobal = GlobalAlloc(GMEM_ZEROINIT, sizeof(DLGTEMPLATE)); if (m_hGlobal != NULL) { m_pDlgTemplate = (DLGTEMPLATE*)GlobalLock(m_hGlobal); } } ~MessageWindow() { if (m_hGlobal != NULL) { if (m_pDlgTemplate != NULL) { GlobalUnlock(m_hGlobal); m_pDlgTemplate = NULL; } GlobalFree(m_hGlobal); m_hGlobal = NULL; } } public: HGLOBAL m_hGlobal = NULL; DLGTEMPLATE*m_pDlgTemplate = NULL; TSTRING m_strCaption = TEXT(""); TSTRING m_strMessage = TEXT(""); HGDIOBJ DEFAULTGUIFONT = GetStockObject(DEFAULT_GUI_FONT); typedef enum CTRLIDTYPE { IDC_STATIC_IMG = (IDC_STATIC + 512), IDC_STATIC_MSG, IDC_TOOLTIP_MSG, }CTRLIDTYPE; INT ICON_WIDTH = 48; INT ICON_HEIGHT = 48; INT BUTTON_WIDTH = 80; INT BUTTON_HEIGHT = 20; HWND m_hTip = NULL; TOOLINFO m_ToolInfo = { 0 }; public: static void SetWindowIcon(HWND hWnd) { DeleteObject((HGDIOBJ)SNDMSG(hWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)SNDMSG(GetParent(hWnd), WM_GETICON, (WPARAM)ICON_BIG, (LPARAM)NULL))); DeleteObject((HGDIOBJ)SNDMSG(hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)SNDMSG(GetParent(hWnd), WM_GETICON, (WPARAM)ICON_SMALL, (LPARAM)NULL))); DeleteObject((HGDIOBJ)SNDMSG(hWnd, WM_SETICON, (WPARAM)ICON_SMALL2, (LPARAM)SNDMSG(GetParent(hWnd), WM_GETICON, (WPARAM)ICON_SMALL2, (LPARAM)NULL))); } static BOOL CALLBACK EnumProcCallBack(HWND hWnd, LPARAM lParam) { SNDMSG(hWnd, WM_SETFONT, (LPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE); return TRUE; } static void UsingDefaultFont(HWND hWnd, LPARAM lParam) { EnumChildWindows(hWnd,(WNDENUMPROC)&MessageWindow::EnumProcCallBack, lParam); } static void SetStaticSystemIcon(HWND hWnd, LPCTSTR lpIconName) { DeleteObject((HGDIOBJ)SNDMSG(hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(NULL, lpIconName))); } static void SetStaticApplicationIcon(HWND hWnd, LPCTSTR lpIconName, HINSTANCE hInstance) { DeleteObject((HGDIOBJ)SNDMSG(hWnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(hInstance, lpIconName))); } static BOOL CALLBACK ProcCallBack(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { MessageWindow* thiz = (MessageWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); switch (uMsg) { case WM_INITDIALOG: { RECT rcDlg = { 0 }; GetClientRect(hWnd, &rcDlg); SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam); thiz = (MessageWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); CreateWindowEx(0, WC_STATIC, TEXT(""), WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE, (rcDlg.right - rcDlg.left - thiz->BUTTON_WIDTH - thiz->ICON_WIDTH) / 2, 0, thiz->ICON_WIDTH, thiz->ICON_HEIGHT, hWnd, (HMENU)IDC_STATIC_IMG, NULL, (LPVOID)lParam); CreateWindowEx(0, WC_STATIC, thiz->m_strMessage.c_str(), WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE | SS_CENTER | SS_OWNERDRAW, 0, thiz->ICON_WIDTH, rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top - thiz->ICON_WIDTH, hWnd, (HMENU)IDC_STATIC_MSG, NULL, (LPVOID)lParam); CreateWindowEx(0, WC_BUTTON, TEXT("是"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rcDlg.right - rcDlg.left - thiz->BUTTON_WIDTH, 0, thiz->BUTTON_WIDTH, thiz->BUTTON_HEIGHT, hWnd, (HMENU)IDYES, NULL, (LPVOID)lParam); CreateWindowEx(0, WC_BUTTON, TEXT("否"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, rcDlg.right - rcDlg.left - thiz->BUTTON_WIDTH, thiz->BUTTON_HEIGHT, thiz->BUTTON_WIDTH, thiz->BUTTON_HEIGHT, hWnd, (HMENU)IDNO, NULL, (LPVOID)lParam); if (thiz->m_strMessage.length() > 512) { thiz->m_hTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, (HMENU)NULL, NULL, NULL); DWORD dwErr = GetLastError(); SetWindowPos(thiz->m_hTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); // Associate the tooltip with the tool. thiz->m_ToolInfo.cbSize = sizeof(thiz->m_ToolInfo); thiz->m_ToolInfo.hwnd = hWnd; thiz->m_ToolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS; thiz->m_ToolInfo.uId = (UINT_PTR)thiz->m_hTip; thiz->m_ToolInfo.lpszText = (LPTSTR)thiz->m_strMessage.c_str(); SNDMSG(thiz->m_hTip, TTM_ADDTOOL, 0, (LPARAM)&thiz->m_ToolInfo); } SetWindowIcon(hWnd); UsingDefaultFont(hWnd, lParam); SetStaticSystemIcon(GetDlgItem(hWnd, IDC_STATIC_IMG), IDI_QUESTION); SetWindowText(hWnd, thiz->m_strCaption.c_str()); } break; case WM_MOUSEMOVE: { TRACKMOUSEEVENT tme = { 0 }; tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; tme.dwHoverTime = HOVER_DEFAULT; tme.hwndTrack = hWnd; TrackMouseEvent(&tme); RECT rcMsg = { 0 }; POINT ptCursor = { 0 }; GetClientRect(GetDlgItem(hWnd, IDC_STATIC_MSG), &rcMsg); ClientToScreen(GetDlgItem(hWnd, IDC_STATIC_MSG), &((LPPOINT)&rcMsg)[0]); ClientToScreen(GetDlgItem(hWnd, IDC_STATIC_MSG), &((LPPOINT)&rcMsg)[1]); GetCursorPos(&ptCursor); if (PtInRect(&rcMsg, ptCursor) == TRUE) { // Activate the tooltip. SNDMSG(thiz->m_hTip, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&thiz->m_ToolInfo); SNDMSG(thiz->m_hTip, TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(ptCursor.x, ptCursor.y)); } else { // InActivate the tooltip. SNDMSG(thiz->m_hTip, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&thiz->m_ToolInfo); } } break; case WM_MOUSELEAVE: { // InActivate the tooltip. SNDMSG(thiz->m_hTip, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&thiz->m_ToolInfo); } break; case WM_GETMINMAXINFO: { MINMAXINFO* mminfo = (PMINMAXINFO)lParam; /*mminfo->ptMinTrackSize.x = thiz->m_MinSize.cx; mminfo->ptMinTrackSize.y = thiz->m_MinSize.cy; mminfo->ptMaxSize.x = thiz->m_MaxSize.cx; mminfo->ptMaxSize.y = thiz->m_MaxSize.cy; mminfo->ptMaxPosition.x = 0; mminfo->ptMaxPosition.y = 0; mminfo->ptMaxTrackSize.x = thiz->m_MaxSize.cx; mminfo->ptMaxTrackSize.y = thiz->m_MaxSize.cy;*/ } break; case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam; //声明一个指向DRAWITEMSTRUCT结构体的指针并将其指向存储着按钮构造信息的lParam switch (lpDIS->CtlID) { case IDC_STATIC_MSG: { int realHeight = 0; RECT itemRect = { 0 }; RECT realRect = { 0 }; GetClientRect(lpDIS->hwndItem, &itemRect); // 获得客户区范围 memcpy(&realRect, &itemRect, sizeof(realRect)); realHeight = DrawText(lpDIS->hDC, thiz->m_strMessage.c_str(), (int)thiz->m_strMessage.length(), &realRect, DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_CALCRECT | DT_EDITCONTROL); // 获得文本高度 realRect.top = ((itemRect.bottom - itemRect.top) - realHeight) / 2; realRect.bottom = realRect.top + realHeight; DrawText(lpDIS->hDC, thiz->m_strMessage.c_str(), (int)thiz->m_strMessage.length(), &realRect, DT_CENTER | DT_VCENTER | DT_EDITCONTROL | DT_WORDBREAK); } break; } } break; case WM_PAINT: { // //PAINTSTRUCT ps = {0}; //HDC hDC= BeginPaint(hWnd, &ps); //EndPaint(hWnd, &ps); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDYES: case IDNO: case IDOK: case IDCANCEL: case IDRETRY: { ::EndDialog(hWnd, LOWORD(wParam)); } break; default: break; } } break; case WM_CLOSE: { ::EndDialog(hWnd, IDCLOSE); } break; case WM_DESTROY: { ::DestroyWindow(hWnd); } break; } return FALSE; } INT_PTR Run(const TSTRING& strMessage, const TSTRING& strCaption, HWND hParent) { m_strMessage = strMessage; m_strCaption = strCaption; m_pDlgTemplate->x = 0; m_pDlgTemplate->y = 0; m_pDlgTemplate->cx = 120; m_pDlgTemplate->cy = 60; m_pDlgTemplate->style = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | DS_MODALFRAME | DS_SETFONT | DS_FIXEDSYS; m_pDlgTemplate->dwExtendedStyle = WS_EX_TOPMOST; m_pDlgTemplate->cdit = 0; return DialogBoxIndirectParam(GetModuleHandle(NULL), (DLGTEMPLATE*)m_pDlgTemplate, hParent, (DLGPROC)&MessageWindow::ProcCallBack, (LPARAM)this); } };
使用例子:
void CPCMDlg::OnNMRClickListProcess(NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); // TODO: Add your control notification handler code here if (pNMItemActivate->iItem != (-1)) { CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PROCESS); TCHAR tText[MAX_PATH] = { 0 }; LVITEM lvi = { 0 }; lvi.mask = LVIF_TEXT; lvi.iItem = pNMItemActivate->iItem; lvi.iSubItem = pNMItemActivate->iSubItem; lvi.pszText = tText; lvi.cchTextMax = sizeof(tText) / sizeof(*tText); pListCtrl->GetItem(&lvi); enum MenuType { MT_CLOSE = WM_USER + WM_NOTIFY, }; POINT pt = { 0 }; HMENU menu = CreatePopupMenu(); AppendMenu(menu, MF_STRING, MT_CLOSE, TEXT("关闭")); GetCursorPos(&pt); switch (TrackPopupMenu(menu, TPM_VERTICAL | TPM_VCENTERALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, GetSafeHwnd(), NULL)) { case MT_CLOSE: { TSTRING tMsg = (TEXT("即将关闭") + TSTRING(tText) + TEXT("?")); if (MessageWindow().Run(tMsg, TEXT("关闭提示"), m_hWnd) == IDYES) { OnOK(); } } break; } } *pResult = 0; }
收藏的用户(0)
X
正在加载信息~
2
最新回复 (0)