Win 32 API 自定义窗口代替messagebox显示
记录一下第一次做项目(研究生)的一个小小需求。如果大家有更好的方法希望大家在评论区留言哦。
需求就是自定义一个窗口代替messagebox,因为messagebox显示有限,所以有这个需求。由于第一次接触这个,在网上找了很多的资料,发现用API做的很少,过程很是心酸,不过也算是苦尽甘来吧,成功还是很开心的。
废话少说直接上代码,新建一个窗口,没有什么特别的
HWND hMsgWindow = CreateWindow(TEXT("RULEJUDGE_WINDOW"), lpCaption, WS_OVERLAPPEDWINDOW , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, GetMyModuleHandle(), NULL);
ShowWindow(hMsgWindow, SW_NORMAL);
UpdateWindow(hMsgWindow);
为什么会选择用控件呢,因为我要显示的文本是通过调用的,由于水平有限,不知道如何把调用参数传递给窗口回调函数里。
如果不在窗口回调函数中的VM_PAINT中显示,那么只要窗口边框调整,窗口内的东西就会重画,另外控件也有很多好处(暂时还没有发现)。
其次这是一个edit控件,而我只需要它显示,所以风格设定了只读。调用显示的内容格式是LPCTSTR,而SetWindowText函数是LPCSTR,所用需要转换,用了CString函数,而这个函数的头文件可以用
#include <atlstr.h>//LPCSTR与LPCTSTR转换
//edit control
hWinRich = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("RichEdit20A"), NULL, ES_MULTILINE | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_READONLY,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hMsgWindow, NULL, NULL, NULL);
GetClientRect(hMsgWindow, &stRect);
hdc = GetDC(hWinRich);
MoveWindow(hWinRich, 0, 0, stRect.right, stRect.bottom, TRUE);
CString str = lpText;
SetWindowText(hWinRich, str);
程序只是简单的实现了替换显示的功能,并不能让要显示的文字适应窗体边框的调整(即如果要显示的文本是一大段,那么它只是显示在一行里,虽然可以用水平滚动条查看),如果哪位大神有思路,麻烦分享一下,最好是有相关的代码,非常感谢。
第一次上手,查到很多资料都是MFC或者WPF的,相比直接这样写代码感觉直接拖控件更简单点。像自动换行,直接设定属性就行,而我用API根本无从下手。
最后:代码有所借鉴,搜的东西实在太多了,忘了借鉴过哪些了,非常感觉你们。
2020.10.30:
将控件风格修改了一下,可以实现自动换行了,但是现在的问题是控件窗体不跟随父窗口改变而改变。
hWinRich = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("RichEdit20A"), NULL, ES_MULTILINE | WS_CHILD | WS_VISIBLE | ES_READONLY | ES_AUTOVSCROLL | ES_VERTICAL,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hMsgWindow, NULL, GetMyModuleHandle(), NULL);
完整的代码如下:
HWND RuleJudgeWindow::CreateMsgWindow(LPCTSTR lpText, LPCTSTR lpCaption)
WNDCLASSEXW wcex;
static TCHAR szAppName[] = TEXT("RULEJUDGE_WINDOW");
MSG msg;
HINSTANCE hRich;
hRich = LoadLibrary(_T("Riched32.dll"));
HDC hdc;
static HWND hWinRich;
RECT stRect;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = RuleJudgeWndProc1;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetMyModuleHandle();//与窗口相关的实例句柄
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = TEXT("RULEJUDGE_WINDOW");
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
HWND hMsgWindow = CreateWindow(TEXT("RULEJUDGE_WINDOW"), lpCaption, WS_OVERLAPPEDWINDOW , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, GetMyModuleHandle(), NULL);
ShowWindow(hMsgWindow, SW_NORMAL);
UpdateWindow(hMsgWindow);
//edit control
hWinRich = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("RichEdit20A"), NULL, ES_MULTILINE | WS_CHILD | WS_VISIBLE | ES_READONLY | ES_AUTOVSCROLL | ES_VERTICAL,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hMsgWindow, NULL, GetMyModuleHandle(), NULL);
GetClientRect(hMsgWindow, &stRect);
hdc = GetDC(hWinRich);
MoveWindow(hWinRich, 0, 0, stRect.right, stRect.bottom, TRUE);
CString str = lpText;
SetWindowText(hWinRich, str);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);//进行消息转换
DispatchMessage(&msg);//发送给窗口回调函数
}
return hMsgWindow;
}
LRESULT CALLBACK RuleJudgeWindow::RuleJudgeWndProc1(HWND hMsgWindow, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
default:
return DefWindowProc(hMsgWindow, message, wParam, lParam);
}
}