WinApi Buttons immer genau in der Mitte Positionieren

02/18/2013 12:53 marykillsjane#1
Guten Tag zusammen.
Ich habe mich gestern entschlossen mithilfe der Tutorials auf WinApi.de langsam mal in die Gui Programmierung in C++ einzusteigen.Es klappt auch bis jetzt alles ganz gut habe bis dato ein Fenster mit einem Button und einem Textfeld erstellt zur Übung.
Nun tut sich mir aber die Frage auf: Muss ich immer mithilfe irgendwelcher Koordinaten "rumexperimentieren" um meine Buttons/ Textfelder etc an den richtigen Platz zu bekommen ,oder gibt es z.B. Funktionen welche mir die Mitte meines Fenster bestimmen können und mir die x/y Koordinaten zurückgeben? Es geht sich darum mein Hauptfenster hat eine Größe von 300 in der Breite und 350 in der höhe wenn ich nun aber einen Button erstelle welcher in der Mitte des Fensters erscheinen soll habe ich mir zuerst gedacht gut ich übergebe diesem dann einfach die hälfte der Werte ( Also 150 in der Breite und 175 in der höhe)wenn ich das aber mache ist der Button nicht in der Mitte ,sondern irgendwo in meinem Fenster.Deshalb wäre es interessant für mich zu erfahren woran das denn liegt ,und wie ich Buttons/ Textfelder etc nun mittig platzieren kann ohne das "rumprobieren".Außerdem geht es mir darum ,dass wenn mein Fenster maximiert sind die Buttons natürlich auch an ganz anderen Koordinaten sind als vorher ,sprich wenn ich in der normalen Fenstergröße einen Button mittig platziert habe dieses Fenster aber maximiert wird ist er irgendwo nur nichtmehr mittig :D.
Ich hoffe ihr versteht soweit was mein Problem ist hier ist noch mein Quellcode falls es jmd hilft:
Code:
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
                   PSTR szCmdLine, int iCmdShow)
{
   MSG        msg;
   HWND       hWnd;
   WNDCLASS   wc;
   
   const char szAppName[]  = "Windows Buttons";
   
   wc.cbClsExtra           = 0;
   wc.cbWndExtra           = 0;
   wc.hbrBackground        =  CreateSolidBrush( RGB(80,20,100)) ;


   wc.hCursor              = LoadCursor(NULL, IDC_ARROW);
   wc.hIcon                = LoadIcon(NULL, IDI_APPLICATION);
   wc.hInstance            = hInstance;
   wc.lpfnWndProc          = WndProc;
   wc.lpszClassName        = szAppName;
   wc.lpszMenuName         = NULL;
   wc.style                = CS_HREDRAW | CS_VREDRAW;
   
   RegisterClass(&wc);
   
   hWnd = CreateWindow(    szAppName,
                           szAppName,
                         WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX , //WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT,          /* X-Position auf dem Monitor */
                       CW_USEDEFAULT,          /* Y-Position auf dem Monitor */
                       350,          /* Fensterbreite              */
                      300,          /* Fensterhoehe               */
                           NULL,
                           NULL,
                           hInstance,
                           NULL);
   
   ShowWindow(hWnd, iCmdShow);
   UpdateWindow(hWnd);
   
   while (GetMessage(&msg, NULL, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   
   return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ static HWND hButton;
   
   switch (message)
   {

   case WM_PAINT:
	   {
	   PAINTSTRUCT ps;
       HDC         hDC;
	   const char  szText[] = "Hallo, dies ist der Text.";
	   hDC = BeginPaint(hWnd, &ps);
        {        
	    TextOut(hDC, 90, 12, szText, sizeof(szText) - 1);   //2 Parameter von Links 3. von oben
        }
        EndPaint(hWnd, &ps);
		   return 0;
      }
	   
	   


   case WM_CREATE:
      {
	    hButton = CreateWindow(  "button",
                                  "Button1",
                                  WS_CHILD | WS_VISIBLE,
                                  0, 0, 0, 0,
                                  hWnd,
                                  NULL,
                                  ((LPCREATESTRUCT) lParam) -> hInstance,
                                  NULL);
         return 0;
      }
   case WM_SIZE:
      {    MoveWindow(hButton,150,175,100,20, TRUE);
         return 0;
      }  
   case WM_COMMAND:
      {
         if (lParam == (LPARAM)hButton)
         {
            if (HIWORD(wParam) == BN_CLICKED)
               MessageBox(hWnd,"Button wurde geklickt","Juhu",NULL);
			  SendMessage(hWnd, WM_CLOSE, 0, 0);

         }
         return 0;
      }
   case WM_DESTROY:
      {
         PostQuitMessage(0);
         return 0;
      }
   }
   return DefWindowProc(hWnd, message, wParam, lParam);
}
02/18/2013 17:10 snow#2
Ich kann nur von Objective-C und nicht von C++ und der WinAPI berichten, aber das sollte am Ende im Prinzip der selbe Vorgang sein:

Du übergibst ja die X-Position und Y-Position. Soweit ich weiß, geht das Programm im Normalfall davon aus, dass diese X/Y-Postion oben links von deinem Objekt (Button, Fenster, Label, wie auch immer) ist. Also an der linken oberen Ecke.

Wenn der Button jetzt in der Mitte sein soll, musst du also als X-Koordinate die Hälfte der Fensterbreite nehmen und die Hälfte deines Buttons abziehen. Also z.B. 150 - (button.width / 2).

Damit es beim Resizen angepasst wird: Hm, da gibt es bestimmt eine Funktion, die beim Resizen aufgerufen wird / überschrieben werden kann? Wie in Java halt.
Da musst du dann den Frame des Buttons dann neu anpassen, wieder mit window.width / 2 - button.width / 2.

So sollte das zumindest theoretisch klappen, evtl. hilft es dir ja. :)
02/18/2013 17:45 MrSm!th#3
Jup, fürs Resizen gibts afaik ne Message. Ansonsten wäre da auch noch die Funktion GetWindowRect.