Schonwieder c++/WinAPI

Hallo,
ich habe lange gegoogled und die MSDN gelesen bis sie mir zu den ohren rauskommt und komme nach 2 stunden suche einfach nicht weiter, da mir mein Problem ziemlich suspekt vorkommt habe ich mich dazu entschlossen es hier zu posten, obwohl ich mir langsam vorkomme als würde ich das Forum zuspammen.

Wie dem auch sei.

Ersteinmal hier ein Screenshot, wie das ganze aktuell aussieht um mein Problem näher beschreiben zu können: Screenshot

Ich habe also einmal das Hauptfenster mit dem Menü "Options". Dahinter verbirgt sich ein Dialog mit einer CALLBACK Funktion namens ConDlgProc.

Code:
BOOL CALLBACK ConDlgProc (HWND hCon, UINT message, WPARAM wParam, LPARAM lParam)
{	
	switch(message)
	{
	case WM_INITDIALOG:
		return (TRUE);
	case WM_DESTROY:
	case WM_CLOSE:
		EndDialog(hCon,0);
		break;
	case WM_COMMAND:
		if(HIWORD(wParam) == BN_CLICKED)
				{
					EndDialog(hCon,0);
					NewWindow();
				}
	break;
	default: 
		return (FALSE);
	}
	return 0;
}

Wie man erkennen kann wird nach einem Klick auf den Button der Dialog mit dem Handle "hCon" geschlossen und schließlich eine Funktion namens "NewWindow" aufgerufen.

Code:
void NewWindow()
{
	const char szAppName[] = "bla";
	WNDCLASS   wc;
	
	wc.style         =  CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc   =  WndProcChild;
	
	wc.cbClsExtra    =  0;
	wc.cbWndExtra    =  0;
	
	wc.hInstance     =  (HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE);
	wc.hCursor       =  LoadCursor(NULL,IDC_ARROW);
	wc.hIcon         =  LoadIcon(NULL,IDI_APPLICATION);
	wc.hbrBackground  = (HBRUSH)GetStockObject(LTGRAY_BRUSH); /* std LTGRAY_BRUSH */
	
	wc.lpszClassName =  szAppName;
	wc.lpszMenuName  =  NULL;
	
	wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
	
	RegisterClass(&wc);
	
	hChServer[1][1] = CreateWindow(wc.lpszClassName,
						   (LPCTSTR) wc.lpszClassName,
                           WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW ,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                           400, 210,
                           hWnd,
                           (HMENU)1,
                           (HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),
                           NULL);
						   
	ShowWindow(hChServer[1][1], SW_SHOW); 
	SetFocus(hChServer[1][1]);
        SetForegroundWindow(hChServer[1][1]);
}

Man kann erkennen, dass ich ein Neues Kindfenster erstelle, welches, wie auf dem Screenshot erkennbar, auch wenn ich die Titelleister anklicke, nicht fokusiert wird.
Doch das ist nicht mein einziges Problem. In einer weiteren Funktion namens WndProcChild, die zum eben erstellten Kindfenster gehört, erstelle ich eine EditBox, die ein Kind vom Kindfenster darstellt und die weder angezeigt wird noch sonst irgendetwas tut. Mein Versuch mit SetForeground das Problem irgendwie zu lösen bleibt vergebens.

Code:
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND hChChEdit;
	switch (message)
    {
	    case WM_CREATE:
		{
			hChChEdit = CreateWindow("EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | 
                                    ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
				    20, 20, 100, 100, hChServer[1][1], NULL,
                                    (HINSTANCE)GetWindowLong(hChServer[1][1], GWL_HINSTANCE),
			            NULL);
			
			SetForegroundWindow(hChChEdit);
			SendMessage(hChChEdit, WM_SETTEXT, 0, (LPARAM) "Hello my brave new World, what's going on ? ;)");
			ShowWindow(hChChEdit, SW_SHOW); 
		}
		break;
		
		case WM_SIZE:
		{
			            MoveWindow(hChChEdit, 
                       0, 0,                  
                       LOWORD(lParam), 
                       HIWORD(lParam), 
                       TRUE); 
            return 0; 
		}
		break;
		
		case WM_COMMAND:
		{
			switch(LOWORD(wParam))
			{
				
			}
			break;
		case WM_PAINT:
		{
			
		}
		break;
		
		case WM_CLOSE:
            DestroyWindow(hChServer[1][1]);
        break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
		}
		return 0;
	}
	return 0;
}

Ich bin leider noch ein Laie in Sachen WinAPI, aber konnte zu diesem Problem über Google und die MSDN einfach keine Lösung finden.

Ich möchte mich entschuldigen, falls ich zuviel poste, aber ich bin halt nur in diesem Board Mitglied und nirgendwo anders. Außerdem kenne ich auch keine Anderen Programmierer und kann daher auch nirgends sonst Rat einholen.

Wie auch immer. Vielen Dank im Voraus ^^

eqw0uL
 
Mal ein paar Fagen vorweg:
Soll das ganze eine MDI-Anwendung sein (könnte laut Screenshot fast so aussehen. In dem Fall müsstest du in deiner NewWindow-Funktion hier statt CreateWindow CreateMDIWindow verwenden).
Ist es beabsichtigt, dass vor dem Erstellen des Fensters (Aufruf NewWindow), das Fenster mit dem Menü beendet wird (EndDialog(hCon,0)). In diesem Fall solltest du nicht mehr das Handle des Fensters (mit dem Menü) als Parent-Fenster angeben (kann hier leider nicht nachvollziehen um welches Handle es sich bei hWnd handelt).

Zum Anfang noch ein Tipp um das Handle der Instance herauszubekommen:
verwende statt
GetWindowLong(HWND, GWL_HINSTANCE)
einfach
GetModuleHandle(NULL)
ansonsten gibt es Probleme in deiner WndProcChild bei WM_CREATE
Weiterhin solltest du beim Erstellen des Edit-Fensters statt hChServer[1][1] hier hWnd einsetzen, da das Handle erst nach dem WM_CREATE existiert.

Weiteres:
In deiner NewWindow-Funktion beim Erstellen des Fensters gibst du (HMENU)1 an.
Wenn du hiermit eine ID für das Fenster festlegen willst, musst du einen Wert oberhalb von WM_USER (0x0400)verwenden (z.B. WM_USER+1)
WM_USER through 0x7FFF Integer messages for use by private window classes.
Weiterhin empfehle ich dir beim Erstellen des Edit-Fensters ebenfalls eine ID festzulegen (z.B. am Anfang des Skripts mit #define IDC_MYEDIT WM_USER+2).
Damit lässt sich das Fenster schnell wiederfinden, die Variable müsste dann nicht mehr statisch sein.
Bei WM_SIZE würde das folgendermaßen aussehen:
MoveWindow(GeltDlgItem(hWnd, IDC_MYEDIT), 0, 0, ...

Deine Aufrufe
SetForegroundWindow(hChChEdit);
ShowWindow(hChChEdit, SW_SHOW);
kannst du getrost rausschmeissen.

Noch eins zur WndProcChild. Wenn du selbst nicht zeichnen willst solltest du hier auf WM_PAINT verzichten.

Nun nochmal zur NewWindow-Methode:
Nach dem ShowWindow(...) solltest du auch noch ein UpdateWindow(hChServer[1][1]) machen, damit das Fenster auch neu gezeichnet wird.
Folgendes kann entfallen:
SetForegroundWindow(hChServer[1][1]);
SetFocus(hChServer[1][1]);
Letzeres gibt manchmal in einigen Fällen Probleme. Wenn du den Fokus auf das Fenster setzen möchtest (falls dieses ein Child ist) mach dieses mit
SendMessage(hCon, WM_NEXTDLGCTL, (WPARAM)hChServer[1][1], (LPARAM)TRUE)

Das war jetzt erst mal eine ganze Menge.
 
Ersteinmal ein Dankeschön für deine zu höchst hilfreichen Lösungen.

Nein, es ist keine MDI-Anwendung, aber ich werde gleich erstmal googlen was das überhaupt ist =). "hWnd" ist der Handle des Hauptfensters und hCon nur der Handle eines Dialogs. Deine Tips waren sehr gut. Nur leider weiß ich immernoch nicht wie ich nun den Fokus auf das Kindfenster setze, "SendMessage(hWnd, WM_NEXTDLGCTL, (WPARAM)hChServer[1][1], (LPARAM)TRUE);" hilft mir nicht weiter. Die Titelleiste ist und bleibt grau. Ich habe nochmals in der MSDN geschaut und z.B. BringWindowToTop ausprobiert, jedoch alles vergebens. Außerdem ist es mir nicht möglich irgendeinen Text zu schreiben, zu löschen oder zu markieren (markieren geht sogar bei ES_READONLY), ja sogar der abgeänderte Curser, der kommt wenn man über einem Editfeld mit der Maus ist, erscheint nicht.

Wäre nett wenn du mir nochmal aushelfen könntest!

Danke

eqw0uL
 
Warum erstellst du hierfür nicht eigentlich mit DialogBox(...) ein modales Fenster. Ausserdem wird beim erneuten Aufruf von NewWindow() versucht die (bereits registrierte) Fensterklasse erneut zu registrieren. Wenn du es unbedingt über eine eigene Fensterklasse regeln willst, solltest du dafür Sorge tragen , dass diese während des Programms nur einmal angelegt, oder nach dem Beenden des Fensters die Funktion UnregisterClass(...) aufgerufen wird.

Wenn du deinen Code folgendermaßen änderst, hast du aber wahrscheinlich den gewünschten Effekt
Code:
hChServer[1][1] = CreateWindow(
  wc.lpszClassName,
  (LPCTSTR) wc.lpszClassName,
  WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
  CW_USEDEFAULT, CW_USEDEFAULT,
  400, 210,
  hWnd,
  NULL, //(HMENU) bei übergeordneten Fenstern kannst du hier keine ID festlegen
  (HINSTANCE)GetModuleHandle(NULL),
  NULL);
 
Dein Vorschlag funktioniert soweit. Ich strebe es allerdings an, dass ich das als zweites erstellte Fenster nicht aus der Clientarea des Hauptfensters bewegt haben will, also auch beim Maximieren. Wie auch in der MSDN beschrieben funktionieren WS_POPUP und WS_CHILD nicht miteinander.
Ich hab' versucht Dialogs zu benutzen, nur leider ist mir dann als ich WM_SIZE in der DialogProc nutzen wollte aufgefallen, dass ich keine Handles von den Editboxen aus dem Dialog hab' und auch nich die Edit-felder mit WM_CREATE erstellen kann, also bleiben die Textfelder in der ursprünglichen Größe beim vergrößern des Dialogs.

Danke
eqw0uL

Edit:
Code:
	hChServer[1][1] = CreateWindow(wc.lpszClassName,
						   (LPCTSTR) wc.lpszClassName,
						   WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                           400, 210,
                           hWnd,
                           NULL,
                           GetModuleHandle(NULL),
                           NULL);
						   
	SetParent(hChServer[1][1],hWnd);

Also das funktioniert einwandfrei. Danke für eure Hilfe.

eqw0uL
 
Wenn das Fenster sich immer im Hauptfenster befinden soll ist das Stichwort CreateMDIWindow (wie ich es bereits erwähnt hatte).
Zu den Dialogboxen:
Hier gibt es beim Erstellen keine Message WM_CREATE, sondern WM_INITDIALOG. Wie du an die Handles von den Edit-Fenstern kommst hatte ich auch schon erwähnt (Tipp: GetDlgItem). Das Handle der DialogBox dürfte wohl in der DialogProc(HWND hdlg, UINT message, ...) kein Problem sein.
 
Zurück
Oben