2013-01-04 17 views
0

我试图在透明窗口上绘制GDIplus,并且经历很多闪烁。我读过大量建议实现双缓冲或渲染到离屏表面的线程会有所帮助,但我没有做到这一点。GDIplus闪烁

任何想法我做错了什么,以及如何解决它? 谢谢。

#include <Windows.h> 
#include <stdio.h> 
#include <time.h> 
#include <GdiPlus.h> 

#pragma comment(lib, "GdiPlus.lib") 

HWND hWnd = NULL; 
WNDCLASSEX wcex; 
HDC hdc = NULL; 
PAINTSTRUCT ps; 
HGDIOBJ hfDefault; 
MSG msg; 
COLORREF transKey = RGB(37,14,103); 
ULONG_PTR m_gdiplusToken; 

char window_title[9] = "testings"; 
char window_class[9] = "testings"; 

int window_width = GetSystemMetrics(SM_CXSCREEN); 
int window_height = GetSystemMetrics(SM_CYSCREEN); 

DWORD MainThread(LPVOID lpArgs) 
{ 
    while(1) 
    { 
     RECT rc = {0,0,window_width,window_height}; 
     InvalidateRect(hWnd, &rc, false); 
     UpdateWindow(hWnd); 
     Sleep(50); 
    } 
} 

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    if(msg == WM_CREATE) 
    { 
     hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT); 

     Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
     Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); 

     SetLayeredWindowAttributes(hWnd, transKey, 128, LWA_COLORKEY); 
    } 
    else if(msg == WM_PAINT) 
    { 
     hdc = BeginPaint(hWnd, &ps); 

     Gdiplus::Graphics g(hdc); 

     g.Clear(Gdiplus::Color(37,14,103)); 

     Gdiplus::Bitmap* curBitmap = new Gdiplus::Bitmap(window_width, window_height); 
     Gdiplus::Graphics* g1 = g.FromImage(curBitmap); 

     static int x=1,y=1; 
     // x += 3; 
     y += 2; 

     Gdiplus::Pen pen(Gdiplus::Color(255, 255, 0, 255)); 

     g1->DrawLine(&pen, x, y, window_width/2, window_height/2); 

     g.DrawImage(curBitmap, 0, 0); 

     EndPaint(hWnd, &ps); 
    } 
    else if(msg == WM_CLOSE) 
    { 
     DestroyWindow(hWnd); 
    } 
    else if(msg == WM_DESTROY) 
    { 
     PostQuitMessage(0); 
    } 
    else 
    { 
     return DefWindowProc(hWnd, msg, wParam, lParam); 
    } 

    return 0; 
} 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    HBRUSH hbrBackground = CreateSolidBrush(transKey); 

    wcex.cbSize  = sizeof(WNDCLASSEX); 
    wcex.style   = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = WndProc; 
    wcex.cbClsExtra = 0; 
    wcex.cbWndExtra = 0; 
    wcex.hInstance  = hInstance; 
    wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 
    wcex.hCursor  = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = hbrBackground; 
    wcex.lpszMenuName = NULL; 
    wcex.lpszClassName = window_class; 
    wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 

    if(!RegisterClassEx(&wcex)) 
     return 1; 

    hWnd = CreateWindowEx(
     WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST, 
     window_class, 
     window_title, 
     WS_POPUP, 
     0, 
     0, 
     window_width, 
     window_height, 
     NULL, 
     NULL, 
     hInstance, 
     NULL 
    ); 

    if(!hWnd) 
     return 1; 

    ShowWindow(hWnd, nCmdShow); 
    UpdateWindow(hWnd); 

    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainThread, NULL, NULL, NULL); 

    while(GetMessage(&msg, NULL, 0, 0) > 0) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    Gdiplus::GdiplusShutdown(m_gdiplusToken); 
    return msg.wParam; 
} 
+0

尝试'清除()'g1'而不是'g'。 – chris

+1

搜索'WM_ERASEBKGND' –

+0

顺便说一下,据我所知,你的线程过程应该在技术上具有'__stdcall'调用约定,可以通过改变签名为'DWORD WINAPI MainThread(LPVOID)'来完成。调用'CreateThread'时,您不必将其转换为'LPTHREAD_START_ROUTINE'。 – chris

回答

1

你有你的窗口,这导致窗口在其下方重绘每一个无效的窗口时间上WS_EX_TRANSPARENT属性。尝试删除它。

WS_EX_TRANSPARENT的含义是告诉Windows,您不会在整个窗口表面上绘制(即将部分透明),因此需要确保下面的所有内容都先呈现,以便能够透视。