【问题标题】:Make a win32 window transparent to messages (click, touch, keyboard)使 win32 窗口对消息透明(单击、触摸、键盘)
【发布时间】:2020-12-14 09:26:17
【问题描述】:

我使用此讨论中的源代码(由 wilkie 发布)创建了一个半透明窗口: How to make an OpenGL rendering context with transparent background?

它可以工作,但我希望我的窗口不接收鼠标、触摸和键盘点击消息。 但最重要的是,我希望这些消息(点击、触摸、键盘)能够被位于我的透明窗口下方的应用程序接收。

示例: 我的透明窗口 (TOP_MOST) 位于 NotePad++ 之上。如果我点击我的透明窗口,我希望 NotePad++ 接收此点击,而不是我的透明窗口。

我没有在 Internet 上找到有效的答案。 我看到两种可能性: _ 使我的窗口对所有消息透明 _ 或者我的透明窗口必须接收消息,而不是通过将它们发送到下面的窗口来做出反应和重定向。

在这两种情况下,我都不知道该怎么做 :) 有可能吗?

问候,

用代码编辑:

#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_TRANSPARENT 但它不起作用。我使用 CreateWindowEx(WS_EX_APPWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT,...)。
  • 显然它确实有效,否则它就不会存在。您的代码中一定有问题。
  • 我刚刚使用了“如何使用透明背景制作 OpenGL 渲染上下文?”中的代码。 (威尔基版本)。我刚刚在 CreateWindowEx() 中添加了“WS_EX_TRANSPARENT”。我必须做其他事情吗?在 WindowFunc() 中?或在 PeekMessageLoop() 中?

标签: winapi win32gui


【解决方案1】:

可以在创建表单时添加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);

然后它对我有用:

【讨论】:

  • 谢谢。我试图修改示例代码以使用 WS_EX_LAYERED 和 SetLayeredWindowAttributes 但它不再显示任何内容。我想我必须修改示例的其他部分才能使其正常工作,但我不知道 win32 是否足以解决问题。
  • @Greg “它不再显示任何东西”,我没有重现过这样的问题,您能否提供您的代码示例以便我重现该问题。
  • 对不起。它有效,我修改了一个坏样本。谢谢 ! :)
  • @Greg 嗨,如果这个答案对你有帮助,请随时标记它以帮助有同样问题的人,如果你有任何问题,请告诉我。谢谢。
【解决方案2】:

感谢朱松 - MSFT 和 David Heffernan,这是本文最初发布的修改示例的完整源代码: How to make an OpenGL rendering context with transparent background?

它在透明窗口中显示一个OpenGL三角形并支持点击:

#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() {
    static float angle = 0.0f;
    angle = (angle < 360.0f ) ? angle + 0.01f : 0.0f;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    glRotatef(angle, 0.0f, 0.0f, 1.0f);

    glColor3f(0, 1, 1);
    glBegin(GL_TRIANGLES);                              // Drawing Using Triangles
    glColor4f(1.0f, 0.0f, 0.0f,0.5f);                      // Set The Color To Red
    glVertex3f(0.0f, 1.0f, 0.0f);                  // Top
    glColor4f(0.0f, 1.0f, 0.0f, 0.5f);                      // Set The Color To Green
    glVertex3f(-1.0f, -1.0f, 0.0f);                  // Bottom Left
    glColor4f(0.0f, 0.0f, 1.0f, 0.5f);                      // 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) {
    PAINTSTRUCT ps;

    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_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);

    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);
}

如果它可以帮助其他人,如果你想用 QT 做同样的事情:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    _glWidget = new MyOpenGLWidget(this); // derived from: public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core

   setAttribute(Qt::WA_InputMethodTransparent);
   setAttribute(Qt::WA_TranslucentBackground, true);
   setAttribute(Qt::WA_TransparentForMouseEvents);
   SetForegroundWindow((HWND)winId());
   setWindowFlags(Qt::Window | Qt::FramelessWindowHint |Qt::WindowStaysOnTopHint);

    ui->verticalLayout->addWidget(_glWidget);                      
}

【讨论】:

    猜你喜欢
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多