Nen einfaches Fenster erzeugen
-
Ich habe bisher noch nicht viel mit der Winapi direkt gemacht, ich kann Textausgeben
und mit nem Scrollbalken umgehen, also alles was ich brauche
Aber wie kann ich einfach ein Fenster erstellen, im Grunde als eigene Anwendung,
sprich es soll nichts direkt mit der eigentlichen Anwendung zu tun haben, aber
kein eigenes Programm sein. Geht das überhaupt?Das Anwendungsfenster eines normalen win32 Programmes mit der WinApi sieht ja so aus:
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("SysMets3") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { // UNICODE-Compilierung ist die einzige realistische Fehlermöglichkeit MessageBox (NULL, TEXT ("Programm arbeitet mit Unicode und setzt Windows NT voraus!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Metriken des Systems, V. 3"), WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; }Und dann halt eine Messageloop. Kann ich das jetzt einfach so übernehmen?
Möchte das ganze in einen Thread packen, welcher von dem Hauptprogramm,
einfach Zeichenketten erhält, welche in diesem Fenster ausgegeben werden sollen.Und was noch wichtig wäre, könnte ein so erstelltes Fenster auch für eine
Konsolenanwendung sein, oder geht das nicht?
-
Irgendwie verstehe ich jetzt nicht so genau, wo dein Problem liegt bzw. was genau du überhaupt vorhast

Aber normalerweise hast du nicht für jedes Fenster eine extra Main-Loop (heißt nicht umsonst so)
Also einfach diese Fensterklasse registrieren und dann in WM_PAINT den Text ausgeben, den du z.B. beim Erstellen des Fensters mit übergibst
-
du kannst CreateWindow problemlos mehrmals aufrufen. brauchst halt nur noch ne fensterklasse mit ner anderen callback-funktion also:
LRESULT CALLBACK WndProc2(HWND, UINT, WPARAM, LPARAM); ... wndclass2.lpfnWndProc = WndProc2;das mit dem extra threat ist keine schlechte idee, weil ja das ganze gemehr von wegen GetMessage (&msg, NULL, 0, 0))...immer wieder die callback funktion aufruft und die schleife ja weiter läuft.
dem andern fenster kannst du ja dann auch problemlos nachrichten mittels SendMessage senden.
lw
-
Flenders wie meinst du das? Wenn ich dieses Fenster mit ner eigenen Mainloop
erstelle, dann habe ich doch keine konflikte mit dem anderen oder?
Das entnehme ich im übrigen auch dem Posting von Lawilog. Und würde das ganze denn
auch in ner Konsole funktionieren?
Und benötigt WNDCLASS denn unbedingt den Parameter hInstance oder kann dieser auch
NULL sein?
-
also. ich weiß nicht. vielleicht hat der alte flenders recht, und das geht irgendwie in einem, aber du machst sicherlich auch nix verfehrt, wenn du 2 machst - vorrausgestzt natürlich, du bekommst das mit den threads hin !
beide WNDCLASS-strukturen können die gleiche HINSTANCE haben. du könntest sogar die eine struktur mit der anderen initialisieren (memcpy ?) und dann nur den lpfnWndProc-member ändern. aber egal jetzt.
wie du das mit dem konsolen fenster machst, musst du mal gucken, steht glaub ich, sogar in irgend ner faq.
lw
-
Ich habe keinen Zugriff auf irgendwelche Daten des Programmes, also dieser Teil
muss wirklich eigenständig sein, das soll nen kleines Konsolenfenster geben, damit
ich die Werte in meinen Programmen leichter prüfen kann
-
da du hast sorgen!
welchen compiler benutz du ?
-
VC++ 7.1
-
hm...

für sowas gibt ja auch nen degugger...

ich weiß da net obs geht, weil nen selber net hab, aber wenn du ne konsolen-anwendug erstellst, de windows.h includierst und dann das ganze fenster gesocks mit nei haust, dann müsstest du sowohl cout als auch die windwos funktionen nutzen können...wenn das geht, ist das sicher die einfachste und beste lösung
lw
-
Willst du mich etwa davon abhalten etwas zu programmieren

Also habe es jetzt mal versucht und es schlägt nix fehl (mitm Debugger durchgegangen),
allerdings scheint er in der Message-Loop sofort rauszuspringen, weil mit dem nächsten
Befehl scheint das Programm beendet zu sein, obwohl es trotzdem irgendwie hängt
(hatte ein cout << "test"; dann die Funktion für das Fenster aufgerufen, danach
ein cin.get (); konnte die Anwendung nur durch das X schließen).
-
hm, muss ich mal ausorbieren. schon ok, is ja keine schlechte idee...
grundsätzlich mein ich aber auch, das du die cout's im messange-loop unterbringen solltest...aber da reden wir morgen weiter. ich geh erstaml regenerien...

lw
-
Ok

Nunja das ganze ist etwas größer, man wird wenn das fertig ist, sowas wie cout haben, sieht dann so aus:
Window w; // Ist die Klasse die obengenanntest können soll myOStream cout (w); cout << "Hallo WinAPI-Forum =)" << endl;Ich möchte das ganze so implementieren, dass ich jederzeit das echte cout benutzen
könnte.Wenn es nicht in der Konsole geht wäre ja nicht _so_ schlimm, aber fänd es halt ganz gut

-
Also du willst quasi eine Konsolen-Anwendung, die Fenster aufmachen kann, oder?
Weil das hast du ja bisher noch gar keine Main-Loop (wie das mit 2 Threads wäre weiß ich eh nicht).
Dann müsstest du eigentlich doch den 2. Thread so, wie sonst eine ganz normale Win-Anwendung aufbauen
Du musst dich nur im Main-Thread darum kümmern, dass dieser nicht ausläuft, solange dein 2. Thread noch was zu tun hat.
-
YEEEHAA !

also, pass auf: ich habs! musste ein bischen tricksen, aber ich hab genau das, was du willst: das is ein konsolen-programm das jederzeit auf cout zugreifen kann, nur das es eben ein fenster erstellt

musst halt nur noch sehen, wie du das deinem compiler bebringst (is wie gesagt ne konsolen-ab - das muss man ja glaub ich beim vc++ angeben, ahb ich selber nicht)
so. here it comes:
#include <iostream> #include <windows> using namespace std; HINSTANCE hInst; LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); int main(int argc, char* argv[]) { cout << "Programm startet...\nParameter:" << endl; if(argc == 1) { cout << "(keine)" << endl; } else { for(int i = 1; i < argc; i++) { cout << '[' << i << "] = \"" << argv[i] << '\"' << endl; } } hInst = GetModuleHandle(NULL); WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_OWNDC, MainWndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), CreateSolidBrush(RGB(8, 8, 64)), NULL, "myWindowClass", NULL}; if(RegisterClassEx(&wc)) cout << "Fensterklasse registriert." << endl; else { cout << "! RegisterClassEx()" << endl; return -1; } HWND hWnd = CreateWindow("myWindowClass", "Deine App", WS_TILED | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_SYSMENU | WS_VISIBLE, 100, 100, 300, 200, NULL, NULL, hInst, NULL); if(hWnd) cout << "Fenster erstellt." << endl; else { cout << "! CreateWindow()" << endl; return -1; } ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); MSG msg; while(GetMessage(&msg, NULL, 0, 0) != 0) { TranslateMessage(&msg); DispatchMessage(&msg); } cout << "Over and Out."; return 0; } LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: { cout << "WM_CREATE" << endl; return 0; } case WM_LBUTTONDOWN: { cout << "Mausklick" << endl; return 0; } case WM_SIZE: { cout << "WM_SIZE" << endl; return 0; } case WM_HELP: { cout << "HILFE! ;)" << endl; return 0; } case WM_DESTROY: { cout << "WM_DESTROY" << endl; PostQuitMessage(0); return 0; } default:return(DefWindowProc(hWnd, msg, wParam, lParam)); } }lw
-
Ich verstehe das so, dass du die Konsole nur zu Testzwecken brauchst:
...also dieser Teil muss wirklich eigenständig sein, das soll nen kleines Konsolenfenster geben, damit ich die Werte in meinen Programmen leichter prüfen kann
Daher könntest du es ja auch mal versuchen in deinem Programm eine Konsole zu öffnen. Ich bin mir aber nicht sicher, ob dann cout funktioniert, denke aber schon. Ich probiers mal schnell aus, interessiert mich jetzt.
Also cout und printf funktionieren nicht. Aber mit WriteConsole(...); kann man dann was in die Konsole schreiben.
-
warum nicht meine lösung ?

sie ist einfach und effizient! :p
lw
-
Weil man sie nicht einfach in ein bestehendes Projekt einbauen kann, dafür funktioniert aber auch cout...
AllocConsole(); kannst du einfach in WinMain schreiben und du hast ne Console. Evtl. noch schnell eine Funktion MyPrintf() geschrieben und fertig ist. Aber egal, soll er machen wie er will

-
Danke Lawilog, werds gleich mal testen

Daniel ich will im Grunde ostream aus der Library nachbauen, so dass man den code
nur copy n' paste'n müsste und eben ein myOstream cout erstellen müsste. Die Ausgabe
selbst ist unabhängig von der myOstream Klasse, da ich das über ne Schnittstelle
implementiere, so könnt ich auch das ganze auf nen Konsolenfenster ausgeben.Und vor allem will ich irgendwas, für mich, halbwegssinnvolles programmieren

Lawilog deine Methode dürfte, aber mit jeder Win-Anwendung gehen, da du ja nur das
GetModuleHandle eingefügt hast, wenn ich das richtig sehe.Edit:
Wenn ich darauf Text wie folgt ausgebe, dann kann ich diesen nicht markieren, würd
ich aber gerne um ihn in die Zwischenablage kopieren zu können.PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint (hWnd, &ps) ; TextOut (hdc, 15, 10, "WM_SIZE", lstrlen ("WM_SIZE"));
-
Mag mir keiner helfen

-
Dann darfst du den Text nicht direkt in dein Fenster zeichnen, sondern musst ein entsprechendes Control (z.B. EDIT) nehmen
-
Also einfach ein Edit-Feld welches so groß wie das gesamte Fenster ist?