2408gui,分层窗口2

server/2024/12/22 20:05:54/

原文

先取出上篇文章的代码并找到CreateLayeredWindow函数.

//创建分层窗口
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colBGRA)
{//注册分层窗口RegWindow(hInstance, L"LayeredWindow", DefWindowProc, BLACK_BRUSH);//创建分层窗口HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, hWnd, NULL, hInstance, NULL);//将分层窗口设为本窗口的子窗口SetParent(hLayeredWindow, hWnd);//更新分层窗口,//创建分层窗口的`DC`HDC hLayeredWindowDC = GetDC(hLayeredWindow);HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);//填充`BLENDFUNCTION`结构BLENDFUNCTION blend = { 0 };blend.BlendOp = AC_SRC_OVER;blend.SourceConstantAlpha = 255;blend.AlphaFormat = AC_SRC_ALPHA;//控制显示位置POINT ptDst = { iPosX, iPosY };//控制窗口大小SIZE sizeWnd = { iWidth, iHeight };//为0就行POINT pSrc = { 0, 0 };//创建一副与当前`DC`兼容的位图HBITMAP hCustomBmp = NULL;hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, iWidth, iHeight);//指定`hCustomBmp`到`hCompatibleDC`中SelectObject(hCompatibleDC, hCustomBmp);//填充`bmpInfo`BITMAPINFO bmpInfo = { 0 };bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmpInfo.bmiHeader.biWidth = iWidth;bmpInfo.bmiHeader.biHeight = iHeight;bmpInfo.bmiHeader.biPlanes = 1;bmpInfo.bmiHeader.biCompression = BI_RGB;bmpInfo.bmiHeader.biBitCount = 32;//设置位图中的像素SetDIBits(NULL, hCustomBmp, 0, iHeight, colBGRA, &bmpInfo, DIB_RGB_COLORS);//更新分层窗口UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);//释放`DC`DeleteDC(hLayeredWindowDC);return hLayeredWindow;
}

为了方便,需要把colBGRA中的像素点数据从BGRA为转换为RGBA.

因此需要翻转RGB值的函数,代码如下:

void TurnRGB(COLORREF* srcCols, COLORREF* tagCols, DWORD dwSize, DWORD dwWidth)
{if (!srcCols || !tagCols || dwSize <= dwWidth || dwSize % dwWidth != 0)//若`srcCols`或`tagCols`为`NULL`,意为没有要翻转`源数据`或没有存储翻转后数据的保存地址
//`dwSize<=dwWidth`表明数据宽度大于数据总大小,如何`0w0`,`dwSize%dwWidth!  =0`表明像素点数据若以`dwWidth`为一行的个数,则无法拼成一个矩形,无法构成一个完整的窗口.return;DWORD dwHeight = dwSize / dwWidth;//计算高度for (DWORD index = 0; index < dwSize; index++)//遍历每个像素点并翻转操作{//`col`来存储当前像素点的数据COLORREF col = srcCols[index];//翻转`RGB`值tagCols[index] = RGBA((BYTE)(col >> 16), (BYTE)(col >> 8), (BYTE)col, (BYTE)(col >> 24));}
}

1,srcCols:像素点数据
2,tagCols:接收像素点翻转后的数据的变量
3,dwSize:像素大小(总数量)
4,dwWidth:像素点数据宽度(就是分层窗口的宽)

CreateLayeredWindow前放置上面函数,以方便调用,然后就可小小的改动CreateLayeredWindow:

//创建分层窗口
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colRGBA)
//将变量名`colBGRA`改为`colRGBA`
{DWORD dwColSize = iWidth * iHeight;COLORREF* colBGRA = new COLORREF[dwColSize];TurnRGB(colRGBA, colBGRA, dwColSize, iWidth);//注册分层窗口RegWindow(hInstance, L"LayeredWindow", DefWindowProc, BLACK_BRUSH);//创建分层窗口HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, hWnd, NULL, hInstance, NULL);//将分层窗口设为本窗口的子窗口SetParent(hLayeredWindow, hWnd);//更新分层窗口//创建分层窗口的`DC`HDC hLayeredWindowDC = GetDC(hLayeredWindow);HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);//填充`BLENDFUNCTION`结构BLENDFUNCTION blend = { 0 };blend.BlendOp = AC_SRC_OVER;blend.SourceConstantAlpha = 255;blend.AlphaFormat = AC_SRC_ALPHA;//控制显示位置POINT ptDst = { iPosX, iPosY };//控制窗口大小SIZE sizeWnd = { iWidth, iHeight };//为0就行POINT pSrc = { 0, 0 };//创建一个与当前`DC`兼容的位图HBITMAP hCustomBmp = NULL;hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, iWidth, iHeight);//在`hCompatibleDC`中指定`hCustomBmp`SelectObject(hCompatibleDC, hCustomBmp);//填充`bmpInfo`BITMAPINFO bmpInfo = { 0 };bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmpInfo.bmiHeader.biWidth = iWidth;bmpInfo.bmiHeader.biHeight = iHeight;bmpInfo.bmiHeader.biPlanes = 1;bmpInfo.bmiHeader.biCompression = BI_RGB;bmpInfo.bmiHeader.biBitCount = 32;//设置位图中的像素SetDIBits(NULL, hCustomBmp, 0, iHeight, colBGRA, &bmpInfo, DIB_RGB_COLORS);//..//更新分层窗口UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);//...//释放`DC`DeleteDC(hLayeredWindowDC);return hLayeredWindow;
}

这样就可直接传入RGBA值,而不必先翻转RGBA值为BGRA值再传入了.
然后找到CreateLayeredWindow函数里的这一行:

//注册分层窗口
RegWindow(hInstance, L"LayeredWindow", WindowProc, BLACK_BRUSH);

"WindowProc"改为"DefWindowProc".

//注册分层窗口
RegWindow(hInstance, L"LayeredWindow", DefWindowProc, BLACK_BRUSH);

分层窗口并不需要自己的窗口过程函数,用微软提供的就行.
然后找到这一行:

//创建分层窗口
HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, NULL, NULL, hInstance, NULL);

倒数第四个参数改为hWnd:

//创建分层窗口
HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, hWnd, NULL, hInstance, NULL);

这样调用GetParent函数时,就不会出错返回无效了,这里.
接着找到WinMain函数:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR lpCmdLine, int nCmdShow)
{//注册窗口RegWindow(hInstance, L"WINDOW", WindowProc, WHITE_BRUSH);//创建窗口HWND hWnd = CreateWindow(L"WINDOW", 0,WS_OVERLAPPEDWINDOW, 100, 100, 800, 500, NULL, NULL, hInstance, NULL);//显示窗口ShowWindow(hWnd, SW_SHOW);//更新窗口UpdateWindow(hWnd);//创建`BGRA`数据COLORREF* colBGRA = new COLORREF[100 * 100];//初化ZeroMemory(colBGRA, 100 * 100 * sizeof(COLORREF));//填充半透明蓝色for (int i = 0; i < 100 * 100; i++){//虽然用的是`RGBA`,但实际上是`BGRA`colBGRA[i] = RGBA(233, 0, 0, 128);//                  `R  G  B   A`}//创建分层窗口HWND hLW = CreateLayeredWindow(hInstance, hWnd, 100, 100, 0, 0, colBGRA);//..//消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}    return 0;
}

删除或注解掉14~28行的代码.

...//更新窗口UpdateWindow(hWnd);MSG msg;
...

现在完整代码应该如下:

#include <windows.h>#define         RGBA(r,g,b,a)               (COLORREF)(((BYTE)(r) |((WORD)((BYTE)(g)) << 8)) |(((DWORD)((BYTE)(b)) << 16)) |(((DWORD)((BYTE)(a)) << 24)))//窗口过程函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,    WPARAM wParam, LPARAM lParam)
{switch (Msg){case WM_DESTROY:PostQuitMessage(0);return 0;default:return DefWindowProc(hWnd, Msg, wParam, lParam);}return 0;
}
//注册窗口函数
void RegWindow(HINSTANCE hInstance, LPCWSTR lpClassName, WNDPROC wndProc, DWORD dwColor)
{WNDCLASS wnd;wnd.cbClsExtra = 0;wnd.cbWndExtra = 0;wnd.hbrBackground = (HBRUSH)(GetStockObject(dwColor));wnd.hCursor = LoadCursor(NULL, IDC_ARROW);wnd.hIcon = LoadCursor(NULL, IDI_APPLICATION);wnd.lpfnWndProc = wndProc;wnd.lpszClassName = lpClassName;wnd.lpszMenuName = NULL;wnd.style = CS_HREDRAW;wnd.hInstance = hInstance;RegisterClass(&wnd);
}
void TurnRGB(COLORREF* srcCols, COLORREF* tagCols, DWORD dwSize, DWORD dwWidth)
{if (!srcCols || !tagCols || dwSize <= dwWidth || dwSize % dwWidth != 0)return;//略注释.DWORD dwHeight = dwSize / dwWidth;//计算高度for (DWORD index = 0; index < dwSize; index++)//遍历每个像素点并翻转操作{//`col`来存储当前像素点的数据COLORREF col = srcCols[index];//翻转`RGB`值tagCols[index] = RGBA((BYTE)(col >> 16), (BYTE)(col >> 8), (BYTE)col, (BYTE)(col >> 24));}
}
//创建分层窗口
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colRGBA)
//将变量名`colBGRA`改为`colRGBA`
{DWORD dwColSize = iWidth * iHeight;COLORREF* colBGRA = new COLORREF[dwColSize];TurnRGB(colRGBA, colBGRA, dwColSize, iWidth);//注册分层窗口RegWindow(hInstance, L"LayeredWindow", DefWindowProc, BLACK_BRUSH);//创建分层窗口HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, hWnd, NULL, hInstance, NULL);//将分层窗口设为本窗口的子窗口SetParent(hLayeredWindow, hWnd);//更新分层窗口//创建分层窗口的`DC`HDC hLayeredWindowDC = GetDC(hLayeredWindow);HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);//填充`BLENDFUNCTION`结构BLENDFUNCTION blend = { 0 };blend.BlendOp = AC_SRC_OVER;blend.SourceConstantAlpha = 255;blend.AlphaFormat = AC_SRC_ALPHA;//控制显示位置POINT ptDst = { iPosX, iPosY };//控制窗口大小SIZE sizeWnd = { iWidth, iHeight };//为0就行POINT pSrc = { 0, 0 };//创建一副与当前`DC`兼容的位图HBITMAP hCustomBmp = NULL;hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, iWidth, iHeight);//指定`hCustomBmp`到`hCompatibleDC`中SelectObject(hCompatibleDC, hCustomBmp);//填充`bmpInfo`BITMAPINFO bmpInfo = { 0 };bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmpInfo.bmiHeader.biWidth = iWidth;bmpInfo.bmiHeader.biHeight = iHeight;bmpInfo.bmiHeader.biPlanes = 1;bmpInfo.bmiHeader.biCompression = BI_RGB;bmpInfo.bmiHeader.biBitCount = 32;//设置位图中的像素SetDIBits(NULL, hCustomBmp, 0, iHeight, colBGRA, &bmpInfo, DIB_RGB_COLORS);//更新分层窗口UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);//释放`DC`DeleteDC(hLayeredWindowDC);return hLayeredWindow;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR lpCmdLine, int nCmdShow)
{//注册窗口RegWindow(hInstance, L"WINDOW", WindowProc, WHITE_BRUSH);//创建窗口HWND hWnd = CreateWindow(L"WINDOW", 0,WS_OVERLAPPEDWINDOW, 100, 100, 800, 500, NULL, NULL, hInstance, NULL);//显示窗口ShowWindow(hWnd, SW_SHOW);//更新窗口UpdateWindow(hWnd);MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}    return 0;
}

悬停效果

360做示例

其实就是点击一个按钮后有一个框框住了按钮的效果,该效果用来实现三态按钮.如果用纯win32按正常的思路设计会比较麻烦,但用分层窗口就会比较容易.
因为win32的按钮要检测鼠标悬停,无论是原版按钮还是自绘按钮,都比较麻烦.

思路

要先创建几个按钮,然后检测到按下按钮后就移动分层窗口该按钮上,而移动窗口需要MoveWindow函数.这里

BOOL MoveWindow([in] HWND hWnd,[in] int  X,[in] int  Y,[in] int  nWidth,[in] int  nHeight,[in] BOOL bRepaint
);

1,hWnd:要移动的窗口hWnd
2,x,y:要移动到哪里(新位置的坐标)
3,nWidth,nHeight:窗口移动后的大小
4,bRepaint:是否重画

实践

这里先创建4个按钮,而要在WM_CREATE消息里创建创建按钮.
而处理按钮事件需要接收WM_COMMAND消息
找到窗口窗口过程函数WindowProc,添加WM_CREATEWM_COMMAND消息并处理.

LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{switch (Msg){case WM_CREATE:{LPCREATESTRUCT pc = (LPCREATESTRUCT)lParam;break;}case WM_COMMAND:{WORD id = LOWORD(wParam);WORD code = HIWORD(wParam);HWND hwnd = (HWND)lParam;break;}case WM_DESTROY:PostQuitMessage(0);return 0;default:return DefWindowProc(hWnd, Msg, wParam, lParam);}return 0;
}

接着创建4个宽为120,高为150的按钮,分别叫choice1,choice2,choice3,choice4,对应的id分别为1,2,3,4.

...
case WM_CREATE:
{LPCREATESTRUCT pc = (LPCREATESTRUCT)lParam;HWND hButton1 = CreateWindow(L"BUTTON", L"choice1", WS_CHILD | WS_VISIBLE, 10, 10, 120, 150, hWnd, (HMENU)1, pc->hInstance, NULL);HWND hButton2 = CreateWindow(L"BUTTON", L"choice2", WS_CHILD | WS_VISIBLE, 140, 10, 120, 150, hWnd, (HMENU)2, pc->hInstance, NULL);HWND hButton3 = CreateWindow(L"BUTTON", L"choice3", WS_CHILD | WS_VISIBLE, 270, 10, 120, 150, hWnd, (HMENU)3, pc->hInstance, NULL);HWND hButton4 = CreateWindow(L"BUTTON", L"choice4", WS_CHILD | WS_VISIBLE, 400, 10, 120, 150, hWnd, (HMENU)4, pc->hInstance, NULL);break;
}
...

接着在WM_COMMAND消息里处理按下按钮的消息

...
HWND hwnd = (HWND)lParam;
if (id == 1 && code == BN_CLICKED)
{MessageBox(hWnd, L"choice1", L"CLICK", 0);
}
else if (id == 2 && code == BN_CLICKED)
{MessageBox(hWnd, L"choice2", L"CLICK", 0);
}
else if (id == 3 && code == BN_CLICKED)
{MessageBox(hWnd, L"choice3", L"CLICK", 0);
}
else if (id == 4 && code == BN_CLICKED)
{MessageBox(hWnd, L"choice4", L"CLICK", 0);
}
break;
...

接着要创建一个分层窗口实现悬停.
先声明全局变量,并提前声明CreateLayeredWindow函数,还要定义一些分层窗口的方便宏.

...#define         RGBA(r,g,b,a)               (COLORREF)(((BYTE)(r) |((WORD)((BYTE)(g)) << 8)) |(((DWORD)((BYTE)(b)) << 16)) |(((DWORD)((BYTE)(a)) << 24)))#define         LAYERED_WINDOW_WIDTH        120        //分层窗口的宽分层窗口的高
#define         LAYERED_WINDOW_HEIGHT       150        //声明全局变量来保存分层窗口的句柄
//
HWND hLayeredWindow = NULL;
//也要提前声明`TurnRGB`函数否则会出错
void TurnRGB(COLORREF* srcCols, COLORREF* tagCols, DWORD dwSize, DWORD dwWidth);
//声明`CreateLayeredWindow`函数方便在`WindowProc`函数里使用
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colRGBA);
//窗口过程函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,    WPARAM wParam, LPARAM lParam)
...

再在WM_CREATE消息里创建分层窗口.

...
HWND hButton4 = CreateWindow(L"BUTTON", L"choice4", WS_CHILD | WS_VISIBLE, 400, 10, 120, 150, hWnd, (HMENU)4, pc->hInstance, NULL);
//创建一个红色半透明的像素矩阵
COLORREF* col = new COLORREF[120 * 150];
for (size_t i = 0; i < 120 * 150; i++)
//遍历填充颜色
{col[i] = RGBA(255, 0, 0, 20);
}
//创建分层窗口,在`(10,10)`位置创建,可使`分层窗口`与按钮重合
hLayeredWindow = CreateLayeredWindow(pc->hInstance, hWnd, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, 10, 10, col);
if (!hLayeredWindow)//创建失败就取消创建直接结束窗口SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
...

现在只要用MoveWindow函数移动分层窗口就行了

回到WM_COMMAND消息里,删除或注释掉MessageBox函数,并使用MoveWindow函数移动分层窗口当前按钮的位置,代码如下:

...
HWND hwnd = (HWND)lParam;
if (id == 1 && code == BN_CLICKED)
{//`MessageBox(hWnd,L"choice1",L"CLICK",0);`移动分层窗口到当前按钮位置,保持宽高不变,重画窗口,下同MoveWindow(hLayeredWindow, 10, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);
}
else if (id == 2 && code == BN_CLICKED)
{//`MessageBox(hWnd,L"choice2",L"CLICK",0);`MoveWindow(hLayeredWindow, 140, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);
}
else if (id == 3 && code == BN_CLICKED)
{//`MessageBox(hWnd,L"choice3",L"CLICK",0);`MoveWindow(hLayeredWindow, 270, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);
}
else if (id == 4 && code == BN_CLICKED)
{//`MessageBox(hWnd,L"choice4",L"CLICK",0);`MoveWindow(hLayeredWindow, 400, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);
}
break;
...

至此,一般的悬停效果就做好了.
完整代码:

#include <windows.h>#define         RGBA(r,g,b,a)               (COLORREF)(((BYTE)(r) |((WORD)((BYTE)(g)) << 8)) |(((DWORD)((BYTE)(b)) << 16)) |(((DWORD)((BYTE)(a)) << 24)))#define         LAYERED_WINDOW_WIDTH        120        //分层窗口的宽分层窗口的高
#define         LAYERED_WINDOW_HEIGHT       150        //声明全局变量来保存分层窗口的句柄
//
HWND hLayeredWindow = NULL;
//也要提前声明`TurnRGB`函数否则会出错
void TurnRGB(COLORREF* srcCols, COLORREF* tagCols, DWORD dwSize, DWORD dwWidth);
//声明`CreateLayeredWindow`函数方便在`WindowProc`函数里使用
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colRGBA);
//窗口过程函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,    WPARAM wParam, LPARAM lParam)
{switch (Msg){case WM_CREATE:{LPCREATESTRUCT pc = (LPCREATESTRUCT)lParam;HWND hButton1 = CreateWindow(L"BUTTON", L"choice1", WS_CHILD | WS_VISIBLE, 10, 10, 120, 150, hWnd, (HMENU)1, pc->hInstance, NULL);HWND hButton2 = CreateWindow(L"BUTTON", L"choice2", WS_CHILD | WS_VISIBLE, 140, 10, 120, 150, hWnd, (HMENU)2, pc->hInstance, NULL);HWND hButton3 = CreateWindow(L"BUTTON", L"choice3", WS_CHILD | WS_VISIBLE, 270, 10, 120, 150, hWnd, (HMENU)3, pc->hInstance, NULL);HWND hButton4 = CreateWindow(L"BUTTON", L"choice4", WS_CHILD | WS_VISIBLE, 400, 10, 120, 150, hWnd, (HMENU)4, pc->hInstance, NULL);//创建一个红色半透明的像素矩阵COLORREF* col = new COLORREF[120 * 150];for (size_t i = 0; i < 120 * 150; i++)//遍历填充颜色{col[i] = RGBA(255, 0, 0, 20);}//创建分层窗口,在`(10,10)`位置创建,可使分层窗口与按钮重合//hLayeredWindow = CreateLayeredWindow(pc->hInstance, hWnd, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, 10, 10, col);if (!hLayeredWindow)//创建失败就取消创建直接结束窗口SendMessage(hWnd, WM_DESTROY, 0, 0);break;}case WM_COMMAND:{WORD id = LOWORD(wParam);WORD code = HIWORD(wParam);HWND hwnd = (HWND)lParam;if (id == 1 && code == BN_CLICKED){//`MessageBox(hWnd,L"choice1",L"CLICK",0);`移动分层窗口到当前按钮位置,保持宽高不变,重画窗口,下同MoveWindow(hLayeredWindow, 10, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);}else if (id == 2 && code == BN_CLICKED){//`MessageBox(hWnd,L"choice2",L"CLICK",0);`MoveWindow(hLayeredWindow, 140, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);}else if (id == 3 && code == BN_CLICKED){//`MessageBox(hWnd,L"choice3",L"CLICK",0);`MoveWindow(hLayeredWindow, 270, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);}else if (id == 4 && code == BN_CLICKED){//`MessageBox(hWnd,L"choice4",L"CLICK",0);`MoveWindow(hLayeredWindow, 400, 10, LAYERED_WINDOW_WIDTH, LAYERED_WINDOW_HEIGHT, TRUE);}break;}case WM_DESTROY:PostQuitMessage(0);return 0;default:return DefWindowProc(hWnd, Msg, wParam, lParam);}return 0;
}
//注册窗口函数
void RegWindow(HINSTANCE hInstance, LPCWSTR lpClassName, WNDPROC wndProc, DWORD dwColor)
{WNDCLASS wnd;wnd.cbClsExtra = 0;wnd.cbWndExtra = 0;wnd.hbrBackground = (HBRUSH)(GetStockObject(dwColor));wnd.hCursor = LoadCursor(NULL, IDC_ARROW);wnd.hIcon = LoadCursor(NULL, IDI_APPLICATION);wnd.lpfnWndProc = wndProc;wnd.lpszClassName = lpClassName;wnd.lpszMenuName = NULL;wnd.style = CS_HREDRAW;wnd.hInstance = hInstance;RegisterClass(&wnd);
}
void TurnRGB(COLORREF* srcCols, COLORREF* tagCols, DWORD dwSize, DWORD dwWidth)
{if (!srcCols || !tagCols || dwSize <= dwWidth || dwSize % dwWidth != 0)return;DWORD dwHeight = dwSize / dwWidth;//计算高度for (DWORD index = 0; index < dwSize; index++)//遍历每个像素点并翻转操作{//`col`来存储当前像素点的数据COLORREF col = srcCols[index];//翻转`RGB`值tagCols[index] = RGBA((BYTE)(col >> 16), (BYTE)(col >> 8), (BYTE)col, (BYTE)(col >> 24));}
}
//创建分层窗口
HWND CreateLayeredWindow(HINSTANCE hInstance, HWND hWnd, int iWidth, int iHeight, int iPosX, int iPosY, COLORREF* colRGBA)
//将变量名`colBGRA`改为`colRGBA`
{DWORD dwColSize = iWidth * iHeight;COLORREF* colBGRA = new COLORREF[dwColSize];TurnRGB(colRGBA, colBGRA, dwColSize, iWidth);//注册分层窗口RegWindow(hInstance, L"LayeredWindow", DefWindowProc, BLACK_BRUSH);//创建分层窗口HWND hLayeredWindow = CreateWindowEx(WS_EX_LAYERED, L"LayeredWindow", 0,WS_POPUP | WS_BORDER, 0, 0, iWidth, iHeight, hWnd, NULL, hInstance, NULL);//将分层窗口设为本窗口的子窗口SetParent(hLayeredWindow, hWnd);//更新分层窗口//创建分层窗口的`DC`HDC hLayeredWindowDC = GetDC(hLayeredWindow);HDC hCompatibleDC = CreateCompatibleDC(hLayeredWindowDC);//填充`BLENDFUNCTION`结构BLENDFUNCTION blend = { 0 };blend.BlendOp = AC_SRC_OVER;blend.SourceConstantAlpha = 255;blend.AlphaFormat = AC_SRC_ALPHA;//控制显示位置POINT ptDst = { iPosX, iPosY };//控制窗口大小SIZE sizeWnd = { iWidth, iHeight };//为0就行POINT pSrc = { 0, 0 };//创建一副与当前`DC`兼容的位图HBITMAP hCustomBmp = NULL;hCustomBmp = CreateCompatibleBitmap(hLayeredWindowDC, iWidth, iHeight);//指定`hCustomBmp`到`hCompatibleDC`中SelectObject(hCompatibleDC, hCustomBmp);//填充`bmpInfo`BITMAPINFO bmpInfo = { 0 };bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bmpInfo.bmiHeader.biWidth = iWidth;bmpInfo.bmiHeader.biHeight = iHeight;bmpInfo.bmiHeader.biPlanes = 1;bmpInfo.bmiHeader.biCompression = BI_RGB;bmpInfo.bmiHeader.biBitCount = 32;//设置位图中的像素SetDIBits(NULL, hCustomBmp, 0, iHeight, colBGRA, &bmpInfo, DIB_RGB_COLORS);//更新分层窗口UpdateLayeredWindow(hLayeredWindow, hLayeredWindowDC, &ptDst, &sizeWnd, hCompatibleDC, &pSrc, NULL, &blend, ULW_ALPHA);//释放`DC`DeleteDC(hLayeredWindowDC);return hLayeredWindow;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR lpCmdLine, int nCmdShow)
{//注册窗口RegWindow(hInstance, L"WINDOW", WindowProc, WHITE_BRUSH);//创建窗口HWND hWnd = CreateWindow(L"WINDOW", 0,WS_OVERLAPPEDWINDOW, 100, 100, 800, 500, NULL, NULL, hInstance, NULL);//显示窗口ShowWindow(hWnd, SW_SHOW);//更新窗口UpdateWindow(hWnd);MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}    return 0;
}

当然,还可添加滑动效果让它更高级一点,


http://www.ppmy.cn/server/104120.html

相关文章

Verilog刷题笔记50

题目&#xff1a; Given the following state machine with 1 input and 2 outputs: 解题&#xff1a; module top_module(input in,input [9:0] state,output [9:0] next_state,output out1,output out2);assign next_state[0]~in&(state[0]|state[1]|state[2]|state[3]…

C语言小练习(伍)

练习&#xff1a; 利用指针变量将一个数组中的数据反向输出。 void renew(int *p,int len) {for(int i len - 1;i > 0;i--){printf("%d",*(pi));} }int main() {int a[5] {1,2,3,4,5};int len1 sizeof(a) / sizeof(int);renew(a,len1);return 0; }运行结果: …

Maven命令传pom或者jar异常

上传命令&#xff1a;mvn deploy:deploy-file -Durlhttp://****&#xff1a;****/repository/chntdrools7741-releases -DrepositoryId**** -DfileD:/tempRepo/org/kie/kie-api-parent/7.69.0.Final/kie-api-parent-7.69.0.Final.pom -DpomFileD:/tempRepo/org/kie/kie-api-par…

2024年特种设备作业人员考试题库及答案(流动式起重机Q2)

一、单选题 371、轮式起重机吊重回转时会产生&#xff08;&#xff09;,所以&#xff0c;起重机司机操纵回转时要特别慎重&#xff0c;回转速度不能过快。 A.向心力 B.咼心力 C.水平力 答案&#xff1a;B 372、为防止起重臂“后倾”造成折臂事故而设置&#xff08;&#…

Windows系统命令

Windows系统命令 Windows 系统中的命令行工具是指令式编程语言&#xff0c;可以用来执行各种任务、管理文件和目录、监控系统状态等。下面是一个 Windows 命令应用实例&#xff1a; 1. 文件操作 cd&#xff1a;用于改变当前目录。例如&#xff0c;cd Documents 将当前目录更…

【Linux】如何快速查看 linux 服务器有几个cpu

如何快速查看 linux 服务器有几个cpu author: jayzhen date: 2024.08.22 文章目录 如何快速查看 linux 服务器有几个cpu1. 使用lscpu命令2. 使用nproc命令3. 使用/proc/cpuinfo文件4. 使用top或htop命令结论 在Linux服务器上&#xff0c;你可以通过多种方式快速查看系统中有几个…

【Mudo库】实战项目之服务器模块

文章目录 前言代码1. Socket1.1 Socket1.2 SSocket1.3 CSocket 2. Poller3. Channel4. Acceptor5. Time5.1 TimerTask5.1 TimerWheel 6. Buffer7. Any8. Connection9. Loop9.1 EventLoop9.2 Thread 10. TcpServer 尾序 前言 在上一篇文章当中对本项目的框架做了一个整体的介绍…

防勒索病毒|防被查盗版|隔离上网

深信达的SPN沙盒安全上网解决方案在防病毒、防被查盗版以及安全上网领域表现出色。该解决方案通过在企业内部部署一个隔离的沙盒环境&#xff0c;实现安全的互联网访问&#xff0c;从而保护本地数据的安全性&#xff0c;防止病毒和木马的入侵。它的核心优势包括&#xff1a; 1.…