winapi - 使 win32 窗口对消息透明(单击、触摸、键盘)
问题描述
我使用此讨论中的源代码(由 wilkie 发布)创建了一个半透明窗口: How to make an OpenGL rendering context with transparent background?
它可以工作,但我希望我的窗口不要接收鼠标、触摸和键盘点击消息。但最重要的是,我希望这些消息(点击、触摸、键盘)能够被位于我的透明窗口下方的应用程序接收。
示例:我的透明窗口 (TOP_MOST) 位于 NotePad ++ 的顶部。如果我点击我的透明窗口,我希望 NotePad++ 而不是我的透明窗口接收此点击。
我没有在互联网上找到有效的答案。我看到两种可能性: _ 使我的窗口对所有消息透明 _ 或者我的透明窗口必须接收消息,而不是通过将它们发送到下面的窗口来做出反应和重定向。
在这两种情况下,我都不知道该怎么做 :) 有可能吗?
问候,
用代码编辑:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <dwmapi.h>
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")
#pragma comment (lib, "dwmapi.lib")
#include <assert.h>
#include <tchar.h>
#ifdef assert
#define verify(expr) if(!expr) assert(0)
#else verify(expr) expr
#endif
const TCHAR szAppName[] = _T("TransparentGL");
const TCHAR wcWndName[] = _T("TransparentGL");
HDC hDC;
HGLRC m_hrc;
int w = 240;
int h = 240;
BOOL initSC() {
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
return 0;
}
void resizeSC(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
BOOL renderSC() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3f(0, 1, 1);
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glColor3f(1.0f, 0.0f, 0.0f); // Set The Color To Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f, 1.0f, 0.0f); // Set The Color To Green
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glColor3f(0.0f, 0.0f, 1.0f); // Set The Color To Blue
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glEnd();
glPopMatrix();
glFlush();
return 0;
}
BOOL CreateHGLRC(HWND hWnd) {
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_SUPPORT_COMPOSITION | // Format Must Support Composition
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
8, // An Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
24, // 16Bit Z-Buffer (Depth Buffer)
8, // Some Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
HDC hdc = GetDC(hWnd);
int PixelFormat = ChoosePixelFormat(hdc, &pfd);
if (PixelFormat == 0) {
assert(0);
return FALSE;
}
BOOL bResult = SetPixelFormat(hdc, PixelFormat, &pfd);
if (bResult == FALSE) {
assert(0);
return FALSE;
}
m_hrc = wglCreateContext(hdc);
if (!m_hrc) {
assert(0);
return FALSE;
}
ReleaseDC(hWnd, hdc);
return TRUE;
}
LRESULT CALLBACK WindowFunc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
break;
case WM_DESTROY:
if (m_hrc) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_hrc);
}
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str, int nWinMode) {
WNDCLASSEX wc;
memset(&wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowFunc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hThisInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(0x00000000);
wc.lpszClassName = szAppName;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, _T("RegisterClassEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT, szAppName, wcWndName,
WS_VISIBLE | WS_POPUP, 200, 150, w, h,
NULL, NULL, hThisInst, NULL);
if (!hWnd) {
MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
DWM_BLURBEHIND bb = { 0 };
HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = hRgn;
bb.fEnable = TRUE;
DwmEnableBlurBehindWindow(hWnd, &bb);
CreateHGLRC(hWnd);
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
initSC();
resizeSC(w, h);
ReleaseDC(hWnd, hdc);
MSG msg;
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
HDC hdc = GetDC(hWnd);
wglMakeCurrent(hdc, m_hrc);
renderSC();
SwapBuffers(hdc);
ReleaseDC(hWnd, hdc);
}
}
return (FALSE);
}
解决方案
您可以WS_EX_LAYERED
在创建窗体时添加样式,并通过该SetLayeredWindowAttributes
函数设置窗口的不透明度。
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_APPWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT, szAppName, wcWndName,
WS_VISIBLE | WS_POPUP, 200, 150, w, h,
NULL, NULL, hThisInst, NULL);
if (!hWnd) {
MessageBox(NULL, _T("CreateWindowEx - failed"), _T("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
然后它对我有用:
推荐阅读
- c# - 尝试在 C# 中访问 Sqlite 数据库
- c++ - DLL 库中相同的静态变量和全局变量
- android - 从资源 id 整数获取颜色给出错误
- mongodb - Ubuntu 16.04 mongo DB 安装失败
- typescript - WebStorm TS:显示所有未使用的函数/变量/模块等
- sql - Oracle SQL 仅将一列值转置为输出中的单独列
- android - android项目中没有发生构建
- vue.js - Vue.js 属性类型检查失败
- 3d-modelling - 如何在 Fusion 360 中的组件之间移动草图和实体
- php - Google Photos API - 有没有办法直接、永久地链接到图像?