【问题标题】:Repaint window problems重绘窗口问题
【发布时间】:2010-05-12 18:13:43
【问题描述】:
#include "stdafx.h"

// Mario Headers
#include "GameMain.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Mario global variables =================
CGameMain* gGameMain;
HWND hWnd;
PAINTSTRUCT ps;
// ========================================



// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

// My unprocess function =====================================
void OnCreate(HWND hWnd)
{
}
void OnKeyUp(WPARAM wParam)
{
    switch (wParam) {
                case VK_LEFT:
                    gGameMain->KeyReleased(LEFT);
                    break;
                case VK_UP:
                    gGameMain->KeyReleased(UP);
                    break;
                case VK_RIGHT:
                    gGameMain->KeyReleased(RIGHT);
                    break;
                case VK_DOWN:
                    gGameMain->KeyReleased(DOWN);
                    break;
    }
}
void OnKeyDown(HWND hWnd,WPARAM wParam)
{
    switch (wParam) {
                case VK_LEFT:
                    gGameMain->KeyPressed(LEFT);
                    break;
                case VK_UP:
                    gGameMain->KeyPressed(UP);
                    break;
                case VK_RIGHT:
                    gGameMain->KeyPressed(RIGHT);
                    break;
                case VK_DOWN:
                    gGameMain->KeyPressed(DOWN);
                    break;
            }
}
void OnPaint(HWND hWnd)
{
   HDC hdc = BeginPaint(hWnd,&ps);

   RECT rect;
   GetClientRect(hWnd,&rect);

   HDC hdcDouble        = CreateCompatibleDC(hdc);
   HBITMAP hdcBitmap    = CreateCompatibleBitmap(hdc,rect.right,rect.bottom);
   HBITMAP bmOld        = (HBITMAP)SelectObject(hdcDouble, hdcBitmap);

   gGameMain->SetHDC(&hdcDouble);
   gGameMain->SendMessage(MESSAGE_PAINT);

   BitBlt(hdc,0,0,rect.right,rect.bottom,hdcDouble,0,0,SRCCOPY);
   SelectObject(hdcDouble,bmOld);
   DeleteDC(hdcDouble);
   DeleteObject(hdcBitmap);
   DeleteDC(hdc);
}

void OnDestroy() 
{
    gGameMain->isPlaying = false;
    EndPaint(hWnd,&ps);
}
// My unprocess function =====================================

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    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_GDIMARIO));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_GDIMARIO);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, 0, NULL, hInstance, NULL);
   if (!hWnd)
   {
      return FALSE;
   }

   // ---------------- Start gdiplus ------------------
   GdiplusStartup(&gdiToken,&gdiStartInput,NULL);
   // -------------------------------------------------

   // Init GameMain
   gGameMain = new CGameMain();

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

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;

        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_KEYDOWN: 
        OnKeyDown(hWnd,wParam);
        break;
    case WM_KEYUP: 
        OnKeyUp(wParam);    
        break;
    case WM_CREATE:
        OnCreate(hWnd);
        break;
    case WM_PAINT:          
        OnPaint(hWnd);
        break;
    case WM_DESTROY:
        OnDestroy();
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_GDIMARIO, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIMARIO));

    // Main message loop:
    // GameLoop

    PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);

    while (gGameMain->isPlaying)
    {
        while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
            if (msg.message == WM_QUIT) 
                break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        if (gGameMain->enterNextState) {
            gGameMain->SendMessage(MESSAGE_ENTER);
            gGameMain->enterNextState = false;
        }

        gGameMain->SendMessage(MESSAGE_UPDATE);
        InvalidateRect(hWnd,NULL,FALSE);
        /*if (gGameMain->exitCurrentState) {
            gGameMain->SendMessage(MESSAGE_EXIT);
            gGameMain->enterNextState = true;
            gGameMain->exitCurrentState = false;
        }*/
        ::Sleep(gGameMain->timer);
            // Do your game stuff here
    }

    GdiplusShutdown(gdiToken); // Shut down gdiplus token

    return (int) msg.wParam;
}

我使用 InvalidateRect(hWnd,NULL,FALSE);对于重绘窗口,但我遇到的问题是当我重绘时 Game struct 没有任何变化。

首先它很好地绘制了我的徽标,第二次(只需调用 InvalidateRect(hWnd,NULL,FALSE); 没有 gGameMain->SendMessage(MESSAGE_ENTER); 这是初始化一些用于绘制的变量。 感谢您阅读本文:)

【问题讨论】:

    标签: c++ gdi+


    【解决方案1】:

    您在每个 wm_paint 消息中调用 BeginPaint(),但在 wm_paint 消息处理程序中没有对 EndPaint() 的相应调用。每个 BeginPaint() 必须与相应的 EndPaint() 匹配。您在 OnDestroy 中的 EndPaint() 调用是无用的。

    另外,不要删除 BeginPaint() 返回的 DC。它是借来的,而不是拥有的。

    其他注意事项:尽量避免在每个 wm_paint 消息上分配新的位图。当窗口改变大小时分配位图,并保留它以供多个 wm_paint 通道重用。

    另请注意,您并未优化绘制以仅绘制剪辑矩形中无效的内容。您正在绘制所有内容,对所有内容进行 blitting,并依靠 GDI 仅获取实际位于剪辑 rect 中的位图的一小部分。随着窗口/位图大小的增加以及您在屏幕上运行的对象/精灵的数量增加,这将成为一个性能问题。你应该只在cliprect中绘制可见的东西。

    【讨论】:

    • 如何使用一张位图。我移动 hdc = BeginPaint(hWnd,&ps);进入 OnPaint 。每次程序执行 hdc = BeginPaint(hWnd,&ps); ,hdc 地址更改,我必须读取 hdcDouble, hdcBitmap 。我是新手,谢谢:)
    • 您也可以提前创建 hdcDouble - 它不必根据 BeginPaint 返回的 hdc 构建。 GetDC(0) 将为屏幕设备返回一个与 CreateCompatibleDC 相同的 dc。如果用户更改屏幕设置,您将需要丢弃 DC,因此您需要听取通知您的相应消息。是的,您确实需要在每个 OnPaint 调用中使用 hdc=BeginPaint(...),但 hdcDouble 不必从该 hdc 构造。 BitBlt 将像素从位图 hdc 复制到屏幕 hdc。
    猜你喜欢
    • 2011-04-13
    • 2020-01-16
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 2011-11-02
    • 1970-01-01
    相关资源
    最近更新 更多