C 自定义窗口样式(标题栏、透明度、形状)
[編輯] [转简体] (简体译文)
|
作者:huidong
| 分類:【編程】Win32
[
10 瀏覽
0 評論
2 贊
2 踩
]
概要
自定义窗口标题栏,透明度(半透明),窗口形状,以及使用PostMessage模拟标题栏拖动,获取窗口标题栏宽高
示例程序:个性的无边框cmd
正文
参考资料
https://codeabc.cn/yangw/a/non-rectangular-window-style?tdsourcetag=s_pctim_aiomsg
圆形形状窗口
用到了获取窗口标题栏宽高的代码:
initgraph(200,200); // 初始化图形窗口 HWND hWnd = GetHWnd(); // 获取窗口句柄 // 获取窗口边框宽高 RECT rcClient, rcWind; GetClientRect(hWnd, &rcClient); GetWindowRect(hWnd, &rcWind); int cx = ((rcWind.right - rcWind.left) - rcClient.right) / 2; int cy = ((rcWind.bottom - rcWind.top + GetSystemMetrics(SM_CYCAPTION)) - rcClient.bottom) / 2; // 设置圆形区域 HRGN rgn = CreateEllipticRgn(0 + cx, 0 + cy, 200 + cx, 200 + cy); SetWindowRgn(hWnd, rgn, true);
窗口透明度设置
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); SetLayeredWindowAttributes(hWnd, 0, 192, LWA_ALPHA); // 设置窗体透明度为 192(0 为全透明,255 为不透明)
需要注意的是,VC6没有声明这个函数,需要动态加载。
窗口标题栏自定义
使用PostMessage告诉windows要拖动窗口
PostMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(m.x, m.y));
1-如果是整个窗口都响应拖动,好办
MOUSEMSG m; // 定义鼠标消息 while(true) { m = GetMouseMsg(); // 获取一条鼠标消息 switch(m.uMsg) { case WM_LBUTTONDOWN: // 如果左键按下,欺骗 windows 点在了标题栏上 PostMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(m.x, m.y)); break; case WM_RBUTTONUP: // 按鼠标右键退出程序 closegraph(); return 0; } }
如果要自绘一个标题栏并且删除win原有的标题栏,请看:
1-删除原有标题栏
SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_CAPTION);
2-重新设置窗口大小,如果没有这句,窗口旁边会出现黑边,这些黑边就是原有的标题栏,所以现在要重新设置窗口大小,把标题栏黑边去掉
SetWindowPos(GetHWnd(), HWND_TOP, 0, 0, 200, 200, SWP_NOMOVE);
3-绘制自己的标题栏
setfillcolor(WHITE); solidrectangle(0, 0, 200, 20);
4-响应拖动标题栏
MOUSEMSG m; // 定义鼠标消息 while (true) { m = GetMouseMsg(); // 获取一条鼠标消息 switch (m.uMsg) { case WM_LBUTTONDOWN: // 如果在标题栏内部 if (m.x > 0 && m.x < 200 && m.y > 0 && m.y < 20) { // 如果左键按下,欺骗 windows 点在了标题栏上 PostMessage(GetHWnd(), WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(m.x, m.y)); } break; case WM_RBUTTONUP: // 按鼠标右键退出程序 closegraph(); return 0; } }
完整示例(自绘标题栏)
#include <graphics.h> #include <conio.h> int WINAPI _tWinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd ) { // 新建绘图窗口 initgraph(200, 200); // 删除标题栏 SetWindowLong(GetHWnd(), GWL_STYLE, GetWindowLong(GetHWnd(), GWL_STYLE) & (!(WS_BORDER)) | WS_VISIBLE); // 去掉标题栏遗留下来的黑边 SetWindowPos(GetHWnd(), HWND_TOP, 0, 0, 200, 200, SWP_NOMOVE); // 画一个蓝色的背景 setbkcolor(BLUE); cleardevice(); // 画一个标题栏 setfillcolor(WHITE); solidrectangle(0, 0, 200, 20); MOUSEMSG m; // 定义鼠标消息 while (true) { m = GetMouseMsg(); // 获取一条鼠标消息 switch (m.uMsg) { case WM_LBUTTONDOWN: // 如果拖动的是标题栏 if (m.x > 0 && m.x < 200 && m.y > 0 && m.y < 20) { // 如果左键按下,欺骗 windows 点在了标题栏上 PostMessage(GetHWnd(), WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(m.x, m.y)); } break; case WM_RBUTTONUP: // 按鼠标右键退出程序 closegraph(); return 0; } } return 0; }
其它更多示例:
EasyXWndPlus
http://www.huidong.xyz/?mode=2&id=91
示例<无边框的个性cmd>
#include <windows.h> #include <thread> void OnWindowMessage() { while (true) { if (GetKeyState(VK_LBUTTON) & 0x8000) { POINT m; GetCursorPos(&m); // 获取鼠标指针位置(屏幕坐标) PostMessage(GetConsoleWindow(), WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(m.x, m.y)); } Sleep(100); } } int main() { // 删除标题栏 SetWindowLong(GetConsoleWindow(), GWL_STYLE, GetWindowLong(GetConsoleWindow(), GWL_STYLE) & (!(WS_BORDER)) | WS_VISIBLE); // 去掉标题栏遗留下来的黑边 SetWindowPos(GetConsoleWindow(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // 开多线程响应窗口拖动 std::thread(OnWindowMessage).detach(); // 启动cmd system("cmd"); return 0; }
效果:
下载:
自定义任何形状的窗口:
参考:http://www.huidong.xyz/index.php?mode=2&id=20