2016-07-01 17 views
0

Ich schreibe ein Programm mit der Win32-API, nur um einen Hang davon zu bekommen und sind auf dieses lästige Problem gestoßen. Nach einer Weile der Größenänderung wird das Fenster minimiert und nachdem es wieder hochgefahren wurde, ist es sichtbar, aber nicht anklickbar und ein Klick darauf aktiviert nur das, was auf dem Fenster darunter ist. Die einzige Lösung ist das Beenden des Programms.Größe ändern Fenster mit Win32 API

Zuerst dachte ich, es wäre wegen meiner benutzerdefinierten Funktion für die Größe des Fensters (ich benutze eine benutzerdefinierte gui und nicht die Standard-Fenstergröße Rahmen), aber dann reaktivierte ich die Standard-sizebox und das Problem blieb immer noch . Es ist schwer zu sagen, aber das Problem scheint konsistent nach etwa der gleichen Zeit/Zecken in der Größe auftreten.

Ich hatte ein ähnliches Problem vorher, wo das Fenster minimieren und dann vollständig weiß werden würde, wenn es wieder heraufgebracht wird, was aus irgendeinem Grund durch eine for-Schleife in der Größenänderungsfunktion verursacht wurde.

Ich habe so viele mögliche Probleme wie möglich im Code ausgeschlossen, aber habe noch keine Lösung gefunden. Im Folgenden finden Sie die Quelldatei, in der der gesamte Code, mit dem das Fenster gezeichnet wird, liegt (mit der Standardgröße).

Ich schätze jede Hilfe, die ich bekommen kann.

Ps. Ich entschuldige mich für jede schlechte Sprache (Nicht-Muttersprachler), falsch verwendete Begriffe oder schlechte Syntax (das erste Mal so weit in die API zu wagen).

//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

Ihr WM_PAINT-Handler verliert Ressourcen wie niemandes. Das ist wahrscheinlich, wo dein Problem herkommt. Die Grenze für GDI-Objekte ist extrem hoch, aber Sie werden es irgendwann treffen, wenn Sie beim Neulackieren wie ein Sieb durchsickern und viele Repaints erzwingen ... Warum lassen Sie das Betriebssystem nicht das tun, wozu das Betriebssystem gedacht ist? Lassen Sie es die Fensterbeschriftung und -rahmen zeichnen, Mausereignisse behandeln und die Größe ändern, usw. –

+4

Auch wenn Sie ein größenveränderbares Fenster ohne einen Rand wünschen, behandeln Sie die 'WM_NCHITTEST' Nachricht und geben Sie den entsprechenden' HT * 'Wert zurück. Lassen Sie dann das OS die Größe des Fensters selbst anpassen. Wenn Sie helfen/kontrollieren/ändern möchten, wie dies geschieht, behandeln Sie die 'WM_WINDOWPOSCHANGING'-Nachricht. – theB

+1

Der WM_SIZE-Handler verliert auch Regionen. –

Antwort

0

Als @CodyGray vorgeschlagen hier ist der Arbeits Code aswell wie die Klasse und den Umgang mit Funktionen Speicher für die Region zu befreien und jetzt auch Bürsten.

Bearbeiten: Das Problem wurde durch einen Speicherverlust in WM_PAINT beim Erstellen und nicht löschen, Bürsten (HBRUSH) verursacht.

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

Auch dank @CodyGray @theB und @AdrianMcCarthy!

Verwandte Themen