2016-07-01 2 views
0

Я пишу программу с помощью API Win32 только для того, чтобы повесить ее и наткнулся на эту неприятную проблему. После небольшого изменения размера окна минимизируется, и после его повторного просмотра он становится видимым, но не кликабельным, и щелчок по нему просто активирует то, что находится в окне под ним. Единственное решение, выходящее из программы.Изменение размера окна с помощью API Win32

Сначала я подумал, что это из-за моей пользовательской функции для калибровки окна (я использую пользовательский gui и не хочу использовать размер окна по умолчанию для Windows), но затем я активировал размер по умолчанию, и проблема все еще сохраняется , Трудно сказать, но проблема, похоже, постоянно возникает после того, как примерно такое же количество времени/тиков будет изменено.

У меня была аналогичная проблема перед тем, где окно скроется, а затем станет полностью белым, когда оно будет снова поднято, что по какой-то причине было вызвано петлей в функции изменения размера.

Я исключил как можно больше потенциальных проблем в коде, но до сих пор не нашел решения. Ниже приведен исходный файл, в котором вся обработка кода, как рисование окна, лежит (с размером по умолчанию).

Я ценю любую помощь, которую я могу получить.

Ps. Я приношу свои извинения за любой плохой язык (не родной язык), неправильно используемые термины или плохой синтаксис (впервые вдаваясь в API).

//WinMain.cpp 

#include <Windows.h> 

#include "Utility.h" 
#include "Mouse.h" 
#include "AppInfo.h" 
#include "Buttons.h" 

//Function prototypes 
ATOM MainRegister(); 
bool MainInit(HWND &hWnd, int nCmdShow); 
void MatchRectToWnd(RECT &rect); 

//Variables define in AppInfo.h 
HRGN rgnMain, rgnCaptionbar; 
bool _APPRUNNING = true; 
const char _APPTITLE[] = "Dark"; 

//Variables 
bool WIREFRAME = false; 

//Pointers to buttons (singelton design) 
btnCloseClass * btnCloseClass::s_Instance = 0; 
btnMaximizeClass * btnMaximizeClass::s_Instance = 0; 
btnMinimizeClass * btnMinimizeClass::s_Instance = 0; 

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (msg) 
    { 
    case WM_LBUTTONDBLCLK: //Left mouse button double-clicked 
     Mouse.CheckDblClick(hWnd, wParam); 
     Mouse.m_Pressed = false; 
    break; 
    case WM_LBUTTONDOWN: //Left mouse button clicked 
     //Update the mouse position variables 
     GetCursorPos(&Mouse.prevPt); 
     GetCursorPos(&Mouse.m_LastClick); 

     Mouse.m_Pressed = true; 

     Mouse.CheckClickDown(hWnd); 
    break; 
    case WM_LBUTTONUP: //Left mouse button released 
    { 
     GetCursorPos(&Mouse.prevPt); 
     Mouse.CheckClickUp(hWnd); 
     Mouse.m_Pressed = false; 
    } 
    break; 
    case WM_SIZE: //Check if the window has been resized 
    { 
     //Update the buttons 
     btnClose->Update(hWnd); 
     btnMaximize->Update(hWnd); 
     btnMinimize->Update(hWnd); 

     //Update the regions 
     RECT rect; GetWindowRect(hWnd, &rect); 
     rgnMain = CreateRectRgn(0, 0, rect.right - rect.left, rect.bottom- rect.top); 
     rgnCaptionbar = CreateRectRgn(0, 0, rect.right - rect.left, CAPTIONBAR_HEIGHT); 

    } 
    break; 
    case WM_PAINT: //Draw the window 
    { 
     HDC hdc; 
     PAINTSTRUCT ps; 
     HBRUSH hBrush; 

     hdc = BeginPaint(hWnd, &ps); 

     //Color the mainregion 
     hBrush = CreateSolidBrush(COLOR_MAIN); 
     FillRgn(hdc, rgnMain, hBrush); 

     //Color the captionbarregion 
     hBrush = CreateSolidBrush(COLOR_CAPTIONBAR); 
     FillRgn(hdc, rgnCaptionbar, hBrush); 

     //Color the button backgrounds 
     hBrush = CreateSolidBrush(COLOR_BUTTON_BACKGROUND); 
     FillRgn(hdc, btnClose->GetRegion(), hBrush); 
     FillRgn(hdc, btnMinimize->GetRegion(), hBrush); 
     FillRgn(hdc, btnMaximize->GetRegion(), hBrush); 

     //Color the button icons 
     hBrush = CreateSolidBrush(COLOR_BUTTON_ICON); 
     FillRgn(hdc, btnClose->GetIcon(), hBrush); 
     FillRgn(hdc, btnMinimize->GetIcon(), hBrush); 
     FillRgn(hdc, btnMaximize->GetIcon(), hBrush); 

     //Paint the wireframe 
     if (WIREFRAME) 
     { 
      hBrush = CreateSolidBrush(COLOR_WIREFRAME); 
      FrameRgn(hdc, rgnMain, hBrush, 1, 1); 
      FrameRgn(hdc, rgnCaptionbar, hBrush, 1, 1); 
      FrameRgn(hdc, btnClose->GetRegion(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMaximize->GetRegion(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMinimize->GetRegion(), hBrush, 1, 1); 
      FrameRgn(hdc, btnClose->GetIcon(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMaximize->GetIcon(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMinimize->GetIcon(), hBrush, 1, 1); 
     } 

     //Free up memomry 
     DeleteObject(hBrush); 
     EndPaint(hWnd, &ps); 
    } 
    break; 
    case WM_KEYDOWN: 
    { 
     switch (wParam) 
     { 
     case VK_TAB: //If TAB is pressed 
     { 
      if (WIREFRAME) //Activate the wireframe 
       WIREFRAME = false; 
      else 
       WIREFRAME = true; 
      InvalidateRgn(hWnd, NULL, true); 
     } 
      break; 
     case VK_ESCAPE: //If the ESCAPE is pressed 
      PostMessage(hWnd, WM_DESTROY, 0, 0); 
      break; 
     } 
    } 
    break; 
    case WM_DESTROY: //Free up memory and exit the program 
     _APPRUNNING = false; 
     DeleteObject(rgnMain); 
     DeleteObject(rgnCaptionbar); 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, msg, wParam, lParam); 
     break; 
    } 
    return 0; 
} 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    HWND hWnd; 
    MSG msg; 
    _APPRUNNING = true; 

    //Register the main window 
    if (!MainRegister()) 
    { 
     MessageBox(hWnd, "Error registering main window!", "Error", MB_ICONERROR); 
     return false; 
    } 

    //Initialize the main window 
    MainInit(hWnd, nCmdShow); 

    //App-loop 
    while (_APPRUNNING) 
    { 
     if ((GetKeyState(VK_LBUTTON) & 0x80) == 0) //Make sure the mouse's status gets updated 
     { 
      Mouse.m_Pressed = false; 
     } 
     Mouse.Update(hWnd); 

     //Message-loop 
     if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) > 0) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 
    return msg.wParam; 
} 

bool MainInit(HWND &hWnd, int nCmdShow) 
{ 
    //Create the window 
    hWnd = CreateWindowEx(
     WS_EX_LAYERED, 
     _APPTITLE, 
     _APPTITLE, 
     WS_OVERLAPPEDWINDOW, 
     0, 0, //Starting positons (x,y) 
     START_WIDTH, START_HEIGHT, //Width and height 
     NULL, //Parent-handle 
     NULL, //Menu-handle 
     GetModuleHandle(NULL), 
     NULL); 

    //Make sure the window was created properly 
    if (hWnd == NULL) 
    { 
     MessageBox(hWnd, "Error initializing main window!", "Error!", MB_ICONERROR); 
     return false; 
    } 

    SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL); 

    //Get and set the window's style 
    DWORD wndStyle = GetWindowLong(hWnd, GWL_STYLE); 
    wndStyle &= ~(WS_CAPTION); 
    SetWindowLong(hWnd, GWL_STYLE, wndStyle); 

    //Create regions 
    rgnMain = CreateRectRgn(0, 0, START_WIDTH, START_HEIGHT); 
    rgnCaptionbar = CreateRectRgn(0, 0, START_WIDTH, CAPTIONBAR_HEIGHT); 

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

    return true; 
} 

ATOM MainRegister() 
{ 
    //Create the window's classEx (extended class) 
    WNDCLASSEX wc; 
    wc.cbClsExtra = 0; 
    wc.cbSize = sizeof(WNDCLASSEX); 
    wc.cbWndExtra = 0; 
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hIcon = NULL; 
    wc.hIconSm = NULL; 
    wc.hInstance = GetModuleHandle(NULL); 
    wc.lpfnWndProc = MainWndProc; 
    wc.lpszClassName = _APPTITLE; 
    wc.lpszMenuName = NULL; 
    wc.style = CS_DBLCLKS; 

    //Register the classEx 
    return RegisterClassEx(&wc); 
} 
+5

Ваш обработчик WM_PAINT утечки ресурсов, как никто. Вероятно, это ваша проблема. Предел для объектов GDI чрезвычайно высок, но вы в конце концов ударите его, если вы просочитесь, как сито, при перекраске и заставите много реплик ... Почему вы не позволяете операционной системе делать то, что предназначена для операционной системы? Пусть он рисует заголовок и рамку окна, обрабатывает события мыши и изменения размера и т. Д. –

+4

Также, если вы хотите изменить размер окна без дескриптора границы сообщения 'WM_NCHITTEST' и вернуть соответствующее значение' HT * '. Затем пусть дескриптор ОС самостоятельно изменит размер окна. Если вы хотите помочь/контролировать/изменять, как это сделать, обработайте сообщение 'WM_WINDOWPOSCHANGING'. – theB

+1

Обработчик WM_SIZE также протекает. –

ответ

0

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

Редактировать: Проблема была вызвана утечкой памяти в WM_PAINT при создании и удалении кистей (HBRUSH).

//WinMain.cpp 

#include <Windows.h> 

#include "Utility.h" 
#include "Mouse.h" 
#include "AppInfo.h" 
#include "Buttons.h" 

//Function prototypes 
ATOM MainRegister(); 
bool MainInit(HWND &hWnd, int nCmdShow); 
void MatchRectToWnd(RECT &rect); 

//Variables define in AppInfo.h 
HRGN rgnMain, rgnCaptionbar; 
bool _APPRUNNING = true; 
const char _APPTITLE[] = "Dark"; 

//Variables 
bool WIREFRAME = false; 

//Pointers to buttons (singelton design) 
btnCloseClass * btnCloseClass::s_Instance = 0; 
btnMaximizeClass * btnMaximizeClass::s_Instance = 0; 
btnMinimizeClass * btnMinimizeClass::s_Instance = 0; 

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (msg) 
    { 
    case WM_LBUTTONDBLCLK: //Left mouse button double-clicked 
     Mouse.CheckDblClick(hWnd, wParam); 
     Mouse.m_Pressed = false; 
    break; 
    case WM_LBUTTONDOWN: //Left mouse button clicked 
     //Update the mouse position variables 
     GetCursorPos(&Mouse.prevPt); 
     GetCursorPos(&Mouse.m_LastClick); 

     Mouse.m_Pressed = true; 

     Mouse.CheckClickDown(hWnd); 
    break; 
    case WM_LBUTTONUP: //Left mouse button released 
    { 
     GetCursorPos(&Mouse.prevPt); 
     Mouse.CheckClickUp(hWnd); 
     Mouse.m_Pressed = false; 
    } 
    break; 
    case WM_SIZE: //Check if the window has been resized 
    { 
     DeleteObject(rgnMain); 
     DeleteObject(rgnCaptionbar); 

     //Update the buttons 
     btnClose->Update(hWnd); 
     btnMaximize->Update(hWnd); 
     btnMinimize->Update(hWnd); 

     //Update the regions 
     RECT rect; GetWindowRect(hWnd, &rect); 
     rgnMain = CreateRectRgn(0, 0, rect.right - rect.left, rect.bottom- rect.top); 
     rgnCaptionbar = CreateRectRgn(0, 0, rect.right - rect.left, CAPTIONBAR_HEIGHT); 
    } 
    break; 
    case WM_PAINT: //Draw the window 
    { 

     HDC hdc; 
     PAINTSTRUCT ps; 
     HBRUSH hBrush; 

     hdc = BeginPaint(hWnd, &ps); 

     //Color the mainregion 
     hBrush = CreateSolidBrush(COLOR_MAIN); 
     FillRgn(hdc, rgnMain, hBrush); 
     DeleteObject(hBrush); 

     //Color the captionbarregion 
     hBrush = CreateSolidBrush(COLOR_CAPTIONBAR); 
     FillRgn(hdc, rgnCaptionbar, hBrush); 
     DeleteObject(hBrush); 

     //Color the button backgrounds 
     FillRgn(hdc, btnClose->GetRegion(), btnClose->GetBrush()); 
     FillRgn(hdc, btnMinimize->GetRegion(), btnMinimize->GetBrush()); 
     FillRgn(hdc, btnMaximize->GetRegion(), btnMaximize->GetBrush()); 

     //Color the button icons 
     FillRgn(hdc, btnClose->GetIcon(), btnClose->GetBrushIcon()); 
     FillRgn(hdc, btnMinimize->GetIcon(), btnMinimize->GetBrushIcon()); 
     FillRgn(hdc, btnMaximize->GetIcon(), btnMaximize->GetBrushIcon()); 

     //Paint the wireframe 
     if (WIREFRAME) 
     { 
      hBrush = CreateSolidBrush(COLOR_WIREFRAME); 
      FrameRgn(hdc, rgnMain, hBrush, 1, 1); 
      FrameRgn(hdc, rgnCaptionbar, hBrush, 1, 1); 
      FrameRgn(hdc, btnClose->GetRegion(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMaximize->GetRegion(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMinimize->GetRegion(), hBrush, 1, 1); 
      FrameRgn(hdc, btnClose->GetIcon(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMaximize->GetIcon(), hBrush, 1, 1); 
      FrameRgn(hdc, btnMinimize->GetIcon(), hBrush, 1, 1); 
      DeleteObject(hBrush); 
     } 

     //Free up memomry 
     DeleteObject(hBrush); 
     EndPaint(hWnd, &ps); 
    } 
    break; 
    case WM_KEYDOWN: 
    { 
     switch (wParam) 
     { 
     case VK_TAB: //If TAB is pressed 
     { 
      if (WIREFRAME) //Activate the wireframe 
       WIREFRAME = false; 
      else 
       WIREFRAME = true; 
      InvalidateRgn(hWnd, NULL, true); 
     } 
     break; 
     case VK_ESCAPE: //If the ESCAPE is pressed 
      PostMessage(hWnd, WM_DESTROY, 0, 0); 
     break; 
     } 
    } 
    break; 
    case WM_DESTROY: //Free up memory and exit the program 
     _APPRUNNING = false; 
     DeleteObject(rgnMain); 
     DeleteObject(rgnCaptionbar); 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, msg, wParam, lParam); 
     break; 
    } 
    return 0; 
} 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    HWND hWnd; 
    MSG msg; 
    _APPRUNNING = true; 

    //Register the main window 
    if (!MainRegister()) 
    { 
     MessageBox(hWnd, "Error registering main window!", "Error", MB_ICONERROR); 
     return false; 
    } 

    //Initialize the main window 
    MainInit(hWnd, nCmdShow); 

    //App-loop 
    while (_APPRUNNING) 
    { 
     if ((GetKeyState(VK_LBUTTON) & 0x80) == 0) //Make sure the mouse's status gets updated 
     { 
      Mouse.m_Pressed = false; 
     } 
     Mouse.Update(hWnd); 

     //Message-loop 
     if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE) > 0) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 
    } 
    return msg.wParam; 
} 

bool MainInit(HWND &hWnd, int nCmdShow) 
{ 
    //Create the window 
    hWnd = CreateWindowEx(
     WS_EX_LAYERED, 
     _APPTITLE, 
     _APPTITLE, 
     WS_OVERLAPPEDWINDOW, 
     0, 0, //Starting positons (x,y) 
     START_WIDTH, START_HEIGHT, //Width and height 
     NULL, //Parent-handle 
     NULL, //Menu-handle 
     GetModuleHandle(NULL), 
     NULL); 

    //Make sure the window was created properly 
    if (hWnd == NULL) 
    { 
     MessageBox(hWnd, "Error initializing main window!", "Error!", MB_ICONERROR); 
     return false; 
    } 

    SetLayeredWindowAttributes(hWnd, NULL, NULL, NULL); 

    //Get and set the window's style 
    DWORD wndStyle = GetWindowLong(hWnd, GWL_STYLE); 
    wndStyle &= ~(WS_CAPTION | WS_SIZEBOX); 
    SetWindowLong(hWnd, GWL_STYLE, wndStyle); 

    //Create regions 
    rgnMain = CreateRectRgn(0, 0, START_WIDTH, START_HEIGHT); 
    rgnCaptionbar = CreateRectRgn(0, 0, START_WIDTH, CAPTIONBAR_HEIGHT); 

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

    return true; 
} 

ATOM MainRegister() 
{ 
    //Create the window's classEx (extended class) 
    WNDCLASSEX wc; 
    wc.cbClsExtra = 0; 
    wc.cbSize = sizeof(WNDCLASSEX); 
    wc.cbWndExtra = 0; 
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hIcon = NULL; 
    wc.hIconSm = NULL; 
    wc.hInstance = GetModuleHandle(NULL); 
    wc.lpfnWndProc = MainWndProc; 
    wc.lpszClassName = _APPTITLE; 
    wc.lpszMenuName = NULL; 
    wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; 

    //Register the classEx 
    return RegisterClassEx(&wc); 
} 

//Button.h 
//Header file for the class responsible for handling the memory of the 
//regions and brushes 
class Button 
{ 
protected: 
    //Protected default constructor 
    Button(); 

    //Protected default destructor 
    ~Button(); 

    //Protected variables 
    HRGN m_Rgn; 
    HRGN m_Icon; 
    HBRUSH m_hBrush; 
    HBRUSH m_hBrush_Icon; 
    bool m_Hovered; 
public: 
    //Public functions 
    virtual void CreateIcon() = 0; 
    virtual void Update(HWND hWnd) = 0; 
    bool Clicked(POINT pt); 
    bool CheckIfHovered(HWND hWnd); 
    HRGN GetRegion() { return m_Rgn; } 
    HRGN GetIcon() { return m_Icon; } 
    HBRUSH GetBrush() { return m_hBrush; } 
    HBRUSH GetBrushIcon() { return m_hBrush_Icon; } 
}; 

//Button.cpp 
//Default constructor 
Button::Button() 
{ 
    m_hBrush = CreateSolidBrush(COLOR_BUTTON_BACKGROUND); 
    m_hBrush_Icon = CreateSolidBrush(COLOR_BUTTON_ICON); 
    m_Hovered = false; 
} 

//Default destructor 
Button::~Button() 
{ 
    //Free up memory 
    DeleteObject(m_Rgn); 
    DeleteObject(m_Icon); 
    DeleteObject(m_hBrush); 
    DeleteObject(m_hBrush_Icon); 
} 

Опять же, благодаря @CodyGray @theB и @AdrianMcCarthy!

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