参考资料
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;
}
效果:
下载:
cmd_no_title.zip
自定义任何形状的窗口:
参考:http://www.huidong.xyz/index.php?mode=2&id=20