2014-09-19 5 views
-1

Я занимаюсь разработкой простого приложения WinAPI для рисования объектов (что-то вроде Paint). Но у меня есть проблема, что, когда пользователь краски объектов несколько минут (3-6), как обычно окно замораживать и не реагировать даже при нажатии на вкладках меню enter image description hereWinAPI приложение замораживания при рисовании

Может быть у кого-то такая же проблема или может предоставить какие-либо решения?

#include "stdafx.h" 
#include "resource.h" 
#include "string.h" 
#include "stdio.h" 

#define MAX_LOADSTRING 100 

/* Global Variables **********************************************************/ 
HINSTANCE hInst; 
TCHAR szTitle[MAX_LOADSTRING]; 
TCHAR szWindowClass[MAX_LOADSTRING];  

int X1 = 0; 
int Y1 = 0; 
int X2 = 0; 
int Y2 = 0; 
bool isPenDrawing = false; 

int lastX = 0; 
int lastY = 0; 

int startRectX = 0; // for ellipse and rectangle 
int startRectY = 0; 

int currentShapeId = 0; 

HDC hdc; 
HDC memDC; 
HDC memDC2; 
HBITMAP memBM; 
HBITMAP memBM2; 
RECT lprect; 
HBRUSH Brush; 
HGDIOBJ hOldBush; 
HPEN Pen; 

/* Forward Declarations ******************************************************/ 
ATOM    MyRegisterClass(HINSTANCE hInstance); 
BOOL    InitInstance(HINSTANCE, int); 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); 


int APIENTRY WinMain(HINSTANCE hInstance, /// MyRegisterClass FUNCTION ALANLOG 
        HINSTANCE hPrevInstance, 
        LPSTR  lpCmdLine, 
        int  nCmdShow) 
{ 
    MSG msg; 
    HACCEL hAccelTable; 
      //C: Initialize the global strings. 
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
    LoadString(hInstance, IDC_PAINT_BEGINNER, szWindowClass, MAX_LOADSTRING); 
      //C: Register the class for the main window of this application. 
    WNDCLASSEX wcex; 

    wcex.cbSize = sizeof(WNDCLASSEX); 

    wcex.style   = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = (WNDPROC)WndProc; 
    wcex.cbClsExtra  = 0; 
    wcex.cbWndExtra  = 0; 
    wcex.hInstance  = hInstance; 
    wcex.hIcon   = LoadIcon(hInstance, (LPCTSTR)IDI_PAINT_BEGINNER); 
    wcex.hCursor  = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
    wcex.lpszMenuName = (LPCSTR)IDC_PAINT_BEGINNER; 
    wcex.lpszClassName = szWindowClass; 
    wcex.hIconSm  = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); 

    RegisterClassEx(&wcex); 
      //C: Perform application initialization. 
    if (!InitInstance (hInstance, nCmdShow)) 
    { 
     return FALSE; 
    } 

    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PAINT_BEGINNER); 
      //C: Main message pump. 
    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 

    return msg.wParam; 
} 


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
    HWND hWnd; 
      //C: Store the instance handle in the global varaible. 
    hInst = hInstance; 
      //C: Create the mainwindow. 
    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 
    if (!hWnd) 
    { 
      //C: The main window creation failed. 
     return FALSE; 
    } 
      //C: Display the main window. 
    ShowWindow(hWnd, nCmdShow); 
      //C: Force the main window to repaint itself. 
    UpdateWindow(hWnd); 

    return TRUE; 
} 


LRESULT OnCommand (HWND hWnd, int iID, int iEvent, HWND hWndControl, bool &isHandled); 
LRESULT OnLButtonDown (HWND hWnd, UINT nCtrl, UINT x, UINT y); 
LRESULT OnMouseMove (HWND hWnd, UINT nCtrl, UINT x, UINT y); 
LRESULT HandleMouseMove(HWND hWnd, UINT nCtrl, int x, int y); 
LRESULT GetCurrentShapeId(HWND hWnd); 
LRESULT OnLButtonUp (HWND hWnd, UINT nCtrl, UINT x, UINT y); 
LRESULT OnPaint  (HWND hWnd); 


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // handler of all windows commands 
{ 
    Brush = CreateSolidBrush(RGB(255, 255, 255)); 
    PAINTSTRUCT ps; 

    switch (message) 
    { 
    case WM_CREATE: 
     { 
      hdc = GetDC(hWnd);     // retrieves a handle to a device context (DC) for the client area 
      memDC = CreateCompatibleDC(hdc); 
      memDC2 = CreateCompatibleDC(hdc); 
      GetClientRect(hWnd, &lprect); 
      memBM = CreateCompatibleBitmap(hdc, lprect.right, lprect.bottom); 
      memBM2 = CreateCompatibleBitmap(hdc, lprect.right, lprect.bottom); 
      SelectObject(memDC, memBM); 
      SelectObject(memDC2, memBM2); 
      FillRect(memDC, &lprect, Brush); 
      FillRect(memDC2, &lprect, Brush); 
      //C: Set the initial drawing mode. 
      HMENU hMenu = ::GetMenu(hWnd); 
      HMENU hMenuShapes = ::GetSubMenu(hMenu, 1); 
     // ::CheckMenuRadioItem(hMenuShapes, ID_SHAPE_RECTANGLE, ID_SHAPE_CIRCLE, ID_SHAPE_RECTANGLE, MF_BYCOMMAND); 
     } 
    case WM_COMMAND: 
     { 
      int wmId = LOWORD(wParam); 
      int wmEvent = HIWORD(wParam); 

      bool isHandled = true; 
      LRESULT lResult = OnCommand(hWnd, wmId, wmEvent, (HWND)lParam, isHandled); 
      if (!isHandled) 
      { 
       lResult = DefWindowProc(hWnd, message, wParam, lParam); 
      } 

      return lResult; 
     } 
     break; 
    case WM_CHAR: 
     { 

     } 
     break; 
    case WM_LBUTTONDOWN: 
     { 
      return 0; 
     } 
     break; 
    case WM_MOUSEMOVE: 
     { 
      int x = LOWORD(lParam); // get mouse position onclick 
      int y = HIWORD(lParam); 
      return HandleMouseMove(hWnd, (UINT)wParam, x, y); 
     } 
     break; 
    case WM_LBUTTONUP: 
     { 
     return 0; 
     } 
     break; 
    case WM_PAINT: 
     { 
      hdc = BeginPaint(hWnd, &ps); 
      BitBlt(hdc, 0, 0, lprect.right, lprect.bottom, memDC2, 0, 0, SRCCOPY); 
      EndPaint(hWnd, &ps); 
     } 
     break; 
    case WM_DESTROY: 
     { 
      //C: Send a shutdown message to the message pump. 
      PostQuitMessage(0); 
      return 0; 
     } 
     break; 
    case WM_RBUTTONDOWN: 
     { 
      int x = LOWORD(lParam); // get mouse position onclick 
      int y = HIWORD(lParam); 

      currentShapeId = ::GetCurrentShapeId(hWnd); 

      if (!isPenDrawing) 
      { 
       isPenDrawing = true; 
       lastX = x; 
       lastY = y; 
       startRectX = x; 
       startRectY = y; 
      } 
      /* 
      char* str1 = new char[50]; 
      char* tmpBuffer = new char[20]; 
      itoa(x, tmpBuffer, 10); 

      strcpy(str1, "Right button DOWN \n X = "); 
      strcat(str1, tmpBuffer); 
      strcat(str1, "\nY = "); 

      itoa(y, tmpBuffer, 10); 
      strcat(str1, tmpBuffer); 


      MessageBox(NULL, (LPCSTR)str1, (LPCSTR)"Message Title", MB_OKCANCEL); 
      */ 

      return 0; 
     } 
     break; 
    case WM_RBUTTONUP: 
     { 
      int x = LOWORD(lParam); // get mouse position onclick 
      int y = HIWORD(lParam); 

      if (isPenDrawing) 
      { 
       BitBlt(memDC, 0, 0, lprect.right, lprect.bottom, memDC2, 0, 0, SRCCOPY); 
       isPenDrawing = false; 
       ClipCursor(NULL);      // free cursor 
       ReleaseCapture(); 
       InvalidateRect(hWnd, &lprect, false); 
      } 

      return 0; 
     } 
     break; 

    } 

      //C: Exit. 
    return DefWindowProc(hWnd, message, wParam, lParam); 
} 

LRESULT HandleMouseMove(HWND hWnd, UINT nCtrl, int x, int y) 
{ 
    if (isPenDrawing) 
    { 
     Brush = (HBRUSH)GetStockObject(HOLLOW_BRUSH); 
     hOldBush = SelectObject(memDC2, Brush); 

     switch (currentShapeId) 
     { 
     case 0: 
      { 
       BitBlt(memDC2, 0, 0, lprect.right, lprect.bottom, memDC, 0, 0, SRCCOPY); 
       Rectangle(memDC2, startRectX, startRectY, x, y); 
       InvalidateRect(hWnd, &lprect, false); 
       lastX = x; 
       lastY = y; 
      } 
      break; 
     case 1: 
      { 

       BitBlt(memDC2, 0, 0, lprect.right, lprect.bottom, memDC, 0, 0, SRCCOPY); 
       Ellipse(memDC2, startRectX, startRectY, x, y); 
       InvalidateRect(hWnd, &lprect, false); 
       lastX = x; 
       lastY = y;     
      } 
      break; 
     case 2: 
      { 
       MoveToEx(memDC2, lastX, lastY, (LPPOINT)NULL); 
       LineTo(memDC2, x, y); 
       BitBlt(memDC, 0, 0, lprect.right, lprect.bottom, memDC2, 0, 0, SRCCOPY); 
       InvalidateRect(hWnd, &lprect, false); 
       lastX = x; 
       lastY = y; 
       break; 
      } 
      break; 
     case 3: 
      { 
       BitBlt(memDC2, 0, 0, lprect.right, lprect.bottom, memDC, 0, 0, SRCCOPY); 

       MoveToEx(memDC2, startRectX, startRectY, (LPPOINT)NULL); 
       LineTo(memDC2, x, y); 

       InvalidateRect(hWnd, &lprect, false); 
       lastX = x; 
       lastY = y; 
      } 
      break; 
     } 

     //::ReleaseDC(hWnd, hdc); 
    } 
    return 0;  
} 


LRESULT GetCurrentShapeId(HWND hWnd) 
{ 
    HMENU hMenu   = ::GetMenu(hWnd); 
    HMENU hShapeMenu = ::GetSubMenu(hMenu, 1); 

    if (::GetMenuState(hShapeMenu, ID_SHAPE_RECTANGLE, MF_BYCOMMAND) & MF_CHECKED) 
    { 
     return 0; 
    } 
    else if (::GetMenuState(hShapeMenu, ID_SHAPE_ELLIPSE, MF_BYCOMMAND) & MF_CHECKED) 
    { 
     return 1; 
    } 
    else if (::GetMenuState(hShapeMenu, ID_SHAPE_PEN, MF_BYCOMMAND) & MF_CHECKED) 
    { 
     return 2; 
    } 
    else if (::GetMenuState(hShapeMenu, ID_SHAPE_LINE, MF_BYCOMMAND) & MF_CHECKED) 
    { 
     return 3; 
    } 
} 


LRESULT OnCommand (HWND hWnd, int iID, int iEvent, HWND hWndControl, bool &isHandled) 
{ 
      //C: Parse the menu selections. 
    switch (iID) 
    { 
    case ID_SHAPE_LINE: 
    case ID_SHAPE_PEN: 
    case ID_SHAPE_RECTANGLE: 
    case ID_SHAPE_ELLIPSE: 
     { 
      //C: Set the drawing mode. 
      HMENU hMenu = ::GetMenu(hWnd); 
      HMENU hMenuShapes = ::GetSubMenu(hMenu, 1); 
      ::CheckMenuRadioItem(hMenuShapes, ID_SHAPE_RECTANGLE, ID_SHAPE_PEN, iID, MF_BYCOMMAND); 
     } 
     break; 
    case IDM_EXIT: 
     { 
      //C: Destroy the window in order to exit the program. 
      DestroyWindow(hWnd); 
     } 
     break; 
    default: 
     { 
      //C: Flag this message as unhandled. 
      isHandled = false; 
     } 
    } 
    return 0; 
} 


LRESULT OnPaint  (HWND hWnd) 
{ 
    PAINTSTRUCT ps; 
    HDC   hdc; 
    hdc = ::BeginPaint(hWnd, &ps); 

    ::EndPaint(hWnd, &ps); 

    return 0; 
} 
+0

Разве ваш отладчик не говорит вам, что делает ваша программа, когда она висит? –

ответ

2

Каждый раз, когда вы вызываете процедуру окна, вы создаете кисть. Который вы тогда не уничтожаете. В конце концов вы исчерпаете системные ресурсы, и тогда ваше приложение перестанет работать.

только создать кисть в коде обработки для конкретных сообщений, которые в этом нуждаются. Убедитесь, что вы уничтожили кисть, когда закончите с ней. Если вы можете создать кисть один раз при запуске и повторно использовать его для жизни приложения, сделайте это.

+0

большое спасибо! вопрос был именно таким. – NETRY

Смежные вопросы