Win32 C++ 实现对话框居中显示

2024-08-27 21:12

本文主要是介绍Win32 C++ 实现对话框居中显示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        使用 MessageBox 对话框显示信息时, 对话框位置总是在屏幕中间, 而不是主窗口的中间, 如何以最简单的方式将对话框移到父窗口中间呢?  那就是使用 CBT 钩子 , 在窗口创建完成前(窗口句柄已经创建完成), 修改窗口的位置, 即可实现对话框在父窗口上居中显示.

首先简单写一个 CBT 钩子类, 这个类暂且叫做 CMessageBoxCenter

MessageBoxCenter.h

#pragma once
#include <windows.h>class CMessageBoxCenter
{public:CMessageBoxCenter();~CMessageBoxCenter();// 获取子窗口位于父窗口的居中位置static POINT GetChildWindowCenterPos(int nWidth,         //子窗口宽度int nHeight,        //子窗口高度HWND hParent        //父窗口句柄);private:// WH_CBT // 线程或全局// https://learn.microsoft.com/zh-cn/windows/win32/winmsg/cbtproc// 安装用于接收对 CBT 应用程序有用的通知的挂钩过程static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam);private:static HHOOK m_hHook;
};

MessageBoxCenter.cpp

#include "MessageBoxCenter.h"HHOOK CMessageBoxCenter::m_hHook;CMessageBoxCenter::CMessageBoxCenter()
{m_hHook = ::SetWindowsHookEx(WH_CBT, CBTProc, NULL, ::GetCurrentThreadId());
}CMessageBoxCenter::~CMessageBoxCenter()
{::UnhookWindowsHookEx(m_hHook);
}POINT CMessageBoxCenter::GetChildWindowCenterPos(int nWidth,         //子窗口宽度int nHeight,        //子窗口高度HWND hParent        //父窗口句柄
)
{RECT rectParent = { 0 };LONG nParentW = 0;LONG nParentH = 0;// 如果父窗口句柄为空, 则以桌面窗口为父窗口if (NULL == hParent){hParent = ::GetDesktopWindow();}// 获取并统计父窗口宽度和高度::GetWindowRect(hParent, &rectParent);nParentW = rectParent.right - rectParent.left;nParentH = rectParent.bottom - rectParent.top;return {rectParent.left + (nParentW - nWidth) / 2, rectParent.top + (nParentH - nHeight) / 2};
}LRESULT CALLBACK CMessageBoxCenter::CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{// 即将创建一个窗口if (HCBT_CREATEWND == nCode){HWND hWndNew = (HWND)wParam;LPCBT_CREATEWND pStruct = (LPCBT_CREATEWND)lParam;HWND hParent = pStruct->lpcs->hwndParent;// 检查是对话框, 则修改显示位置为相对父窗口居中位置if (32770 == ::GetClassLongPtr(hWndNew, GCW_ATOM)){POINT nPos = GetChildWindowCenterPos(pStruct->lpcs->cx, pStruct->lpcs->cy, hParent);pStruct->lpcs->x = nPos.x;pStruct->lpcs->y = nPos.y;}}return ::CallNextHookEx(m_hHook, nCode, wParam, lParam);
}

以下测试例子简单写了个对话框过程, 仅简单测试对话框

main.cpp

#include <windows.h>
#include <tchar.h>
#include <locale.h>
#include"resource.h"
#include "MessageBoxCenter.h"#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")INT_PTR WINAPI DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPSTR lpCmdLine,_In_ int nShowCmd)
{setlocale(LC_ALL, "");UNREFERENCED_PARAMETER(hInstance);UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);UNREFERENCED_PARAMETER(nShowCmd);WORD wID = ::DialogBoxParam(GetModuleHandle(NULL),  MAKEINTRESOURCE(IDD_DIALOG_FRAME), nullptr, DialogProc, (LPARAM)0);return wID;
}INT_PTR WINAPI DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{if (WM_INITDIALOG == uMsg){return (INT_PTR)TRUE;}if (WM_CLOSE == uMsg){::EndDialog(hWnd, 0);return (INT_PTR)TRUE;}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 hWndCtrl = (HWND)lParam;if (wID >= IDOK && wID <= IDNO){::EndDialog(hWnd, wID);}if (IDC_BUTTON_CBT == wID){CMessageBoxCenter boxCenter;MessageBox(hWnd, _T("WH_CBT 钩子测试, 居中显示对话框"), _T("WH_CBT 钩子"), MB_OK);}return (INT_PTR)TRUE;}return (INT_PTR)FALSE;
}

resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Win32Hook.rc 使用
//
#define IDD_DIALOG_FRAME                101
#define IDC_BUTTON_CBT                  1001// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1002
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

Win32Hook.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"/
#undef APSTUDIO_READONLY_SYMBOLS/
// 中文(简体,中国) resources#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//1 TEXTINCLUDE 
BEGIN"resource.h\0"
END2 TEXTINCLUDE 
BEGIN"#include ""winres.h""\r\n""\0"
END3 TEXTINCLUDE 
BEGIN"\r\n""\0"
END#endif    // APSTUDIO_INVOKED/
//
// Dialog
//IDD_DIALOG_FRAME DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "WinHook"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGINDEFPUSHBUTTON   "确定",IDOK,73,142,50,14PUSHBUTTON      "取消",IDCANCEL,181,141,50,14PUSHBUTTON      "WH_CBT 居中显示对话框",IDC_BUTTON_CBT,19,18,91,14
END/
//
// DESIGNINFO
//#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGINIDD_DIALOG_FRAME, DIALOGBEGINLEFTMARGIN, 7RIGHTMARGIN, 302TOPMARGIN, 7BOTTOMMARGIN, 169END
END
#endif    // APSTUDIO_INVOKED/
//
// AFX_DIALOG_LAYOUT
//IDD_DIALOG_FRAME AFX_DIALOG_LAYOUT
BEGIN0
END#endif    // 中文(简体,中国) resources
/#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
///
#endif    // not APSTUDIO_INVOKED

对话框效果

未使用钩子效果

使用钩子后效果:

这篇关于Win32 C++ 实现对话框居中显示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1112797

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python脚本实现自动删除C盘临时文件夹

《Python脚本实现自动删除C盘临时文件夹》在日常使用电脑的过程中,临时文件夹往往会积累大量的无用数据,占用宝贵的磁盘空间,下面我们就来看看Python如何通过脚本实现自动删除C盘临时文件夹吧... 目录一、准备工作二、python脚本编写三、脚本解析四、运行脚本五、案例演示六、注意事项七、总结在日常使用

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

使用Python实现在Word中添加或删除超链接

《使用Python实现在Word中添加或删除超链接》在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能,本文将为大家介绍一下Python如何实现在Word中添加或... 在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能。通过添加超

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一