2017-02-14 1 views
2

Ich erstelle Nachrichtenfenster von meiner Konsolenanwendung. Die Fensterklasse wird korrekt registriert und das Fenster wird korrekt erstellt, es hat jedoch nie einen Titel (während mein Funktionsaufruf createwindow einen Titel angibt). Haben Sie nachgedacht, können Konsolenprogramme Fenster mit Namen erstellen? Googelte es, fand nichts. Dies ist mein Code, auf ein Minimum beschränkt:Erstellte Fenster haben keinen Titel

using namespace std; 
hInstance = GetModuleHandle(NULL); 
WNDCLASS WndClass = {}; 
WndClass.style = CS_HREDRAW | CS_VREDRAW; // == 0x03 
WndClass.lpfnWndProc = pWndProc; 
WndClass.cbClsExtra = 0; 
WndClass.cbWndExtra = 0; 
WndClass.hIcon = 0; 
WndClass.hCursor = 0; 
WndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME; 
WndClass.lpszMenuName = 0; 
WndClass.lpszClassName = "EME.LauncherWnd"; 
int style = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION; 
if (RegisterClassA(&WndClass)) 
{ 
    cout << "class registered. Hinstance : " << hInstance << " style : (expect 0xcf0000) " << std::hex << style << endl; 
    HWND hwind2 = CreateWindowExA(0, "EME.LauncherWnd", "Mytitle", style, 0x80000000, 0x80000000, 0x80000000, 0x80000000, NULL, NULL, hInstance, NULL); 
    if (hwind2 == 0) 
     cout << "Couldn't create window" << endl; 
    else 
     cout << "created window" << endl; 
} 

Ausgang:

class registered. Hinstance : 00E40000 
created window 

Überprüfung mit Nirsoft des Winlister besteht das Fenster, hat die richtige Klasse ("EME.LauncherWnd"), sondern hat kein Name. Darüber hinaus können diese Zeilen Code im Block hinzu:

if (0 == SetWindowText(hwind2, "aTitle")) 
      cout << "couldn't set a title" << endl; 
     else 
      cout << "title set " << endl; 

Der Ausgang ist

title set 

Und doch ist das Fenster noch keinen Titel. Wenn das Konsolenprogramm keinen Titel hätte, würde ich annehmen, dass der Aufruf von SetWindowText 0 zurückgeben würde. Was mache ich falsch? Edit: Hinzufügen von pWndProc angefordert als

LRESULT CALLBACK pWndProc(HWND hwnd,   // Handle to our main window 
    UINT Msg,    // Our message that needs to be processed 
    WPARAM wParam,  // Extra values of message 
    LPARAM lParam)  // Extra values of message 
{ 
     switch (Msg) 

     { 
    case WM_DESTROY: 
.... 
break; 
     } 
} 

Obwohl nach dem Kommentar des pWndProc Hinweis auf (dem Körper, ich war mit dem Bau des Fensters irrelevant gedacht), stellt sie diese Codezeile in dem Schalter als Standard Einfügen aus Fall

return DefWindowProc(hwnd, Msg, wParam, lParam); 

löst das Problem.

+2

"* können Konsolenprogramme Fenster mit Namen erstellen? *" - ja, natürlich. Die Konsole selbst ist schließlich nur eine gewöhnliche Win32-App. Konsolen-Apps haben vollen Zugriff auf die Win32-API. Was bedeutet 'pWndProc' genau und verarbeitet Fenstermeldungen korrekt? –

+0

u nead eine Massage-Schleife –

+0

Voting zu schließen als fehlende reproduzierbare Beispiel. –

Antwort

0

Ich poste die Antwort auf die Frage, wie von einem Kommentar vorgeschlagen: Die Antwort ist, dass für die Fenster Erstellung zu vervollständigen, die pWndProc an RegisterClass übergeben WINAPI muss Standardnachrichten (insbesondere OS Nachrichten) verarbeiten. Während der Ausführung von CreateWindow (nachdem der Aufruf gestartet wurde und bevor er zurückgegeben wurde), empfängt die Funktion pWndProc bereits Nachrichten, die sie verarbeiten muss, in meinem Fall hat sie sie nicht verarbeitet. Dies ist eine Standard pWndProc Funktion:

LRESULT CALLBACK pWndProc(HWND hwnd,   // Handle to our main window 
    UINT Msg,    // Our message that needs to be processed 
    WPARAM wParam,  // Extra values of message 
    LPARAM lParam)  // Extra values of message 
{ 
     switch (Msg) 

     { 
    case WM_DESTROY: 
... 
    default: 
     return DefWindowProc(hwnd, Msg, wParam, lParam); 
     } 
} 

Quelle:

Eine Fensterprozedur in der Regel keine Nachricht ignorieren. Wenn eine Nachricht nicht verarbeitet wird, muss sie die Nachricht zur Standardverarbeitung an das System zurücksenden. Die Fensterprozedur führt dies durch Aufrufen der Funktion DefWindowProc durch, die eine Standardaktion ausführt und ein Nachrichtenergebnis zurückgibt. Die Fensterprozedur muss dann diesen Wert als eigenes Nachrichtenergebnis zurückgeben. Die meisten Fensterprozeduren verarbeiten nur ein paar Nachrichten und leiten die anderen an das System weiter, indem sie DefWindowProc aufrufen.

+0

Hmm, neugierig, dass es überhaupt funktioniert. Die Nicht-Verarbeitung von WM_NCCREATE beendet normalerweise auch das Ende. Nun, Nachrichtenfenster sind speziell, wahrscheinlich warum. Sie sollten ihren Text nicht einstellen, da niemand es sehen kann, sie sollten billig sein. Ein Tool wie Spy ++ kann den Klassennamen anzeigen, genug gut genug. –

+0

@HansPassant Obwohl Fragesteller von Nachrichtenfenstern sprechen, übergibt er 'HWND_MESSAGE' nicht, also ist dies kein Nachrichtenfenster. Ich denke, er hofft nur, es vom Bildschirm zu schieben und zu hoffen, dass es nicht bemerkt wird! –

+0

Ich bin tatsächlich Reverse Engineering ein Programm für Spaß und Erkenntnisgewinn (kein Gewinn). Ich programmiere meinen eigenen Launcher eines MMORPGs, der dazu dient, das Spiel in 5 Sekunden einzuloggen und zu starten, anstatt in der 1 Minute mit dem Launcher. Ich habe mein Fenster auf die gleiche Weise erstellt, wie es die ursprüngliche Firma getan hat (ich habe ihre Argumente und Funktionsaufrufe auf createwindow und registerclass debuggt), und ich benutze die gleichen Titel-/Klassennamen, die nicht mir überlassen sind. – user

Verwandte Themen