Floating Dialog
-
Joa, wieso lässt du da kein Menu aufklappen? So kenne ich das. Ne ListBox habe ich in dem Zusammenhang noch nie gesehen.
-
flenders schrieb:
Schau dir mal unter Using Toolbar Controls den Punkt "Handling Drop-down Buttons" an

Es geht nicht so sehr um die Toolbar. Der Zusammenhang damit ist in meinem Beispiel nicht von Bedeutung. Ich möchte wissen, wie ich ein Popup-Fenster erstelle, das über allen anderen Fenstern steht und, das den Focus des Hauptfensters nicht stiehlt. Ihr braucht euch nur ein Popup-Menu vorstellen. Wenn ich z.B. rechts auf ein Edit-Control klicke dann erscheint ja für gewöhnlich ein Kontextmenü. Ähnlich möchte ich, dass ein Fenster erscheint wenn ich auf einen Button klicke (egal ob normaler Button, oder Toolbarbutton etc.).
In der Beispiel-Funktion bei dem Thema "Handlings Drop-down Buttons" wird ein Popup-Menu erzeugt, was ja ganz simpel ist. Interessant wär das Beispiel gewesen wenn es das gemacht hätte was mir so vorschwebt...
Aber trotzdem danke für den Link. In Zukunft möchte ich nämlich, dass mein Popup-Fenster direkt unter dem Button der Toolbar erscheint. So gesehen, ist der Code nützlich für mich.WebFritzi schrieb:
Joa, wieso lässt du da kein Menu aufklappen? So kenne ich das. Ne ListBox habe ich in dem Zusammenhang noch nie gesehen.
Vielleicht hast du Visual C++ 6.0? Wenn du dort auf den Pfeil neben dem Rückgängig-Button klickst dann erscheint ein Popup-Fenster mit einer ListBox und einem Static Label.
Ich möchte kein Popup-Menu erscheinen lassen. Das erfüllt ganz einfach die Anforderung nicht, die ich mir selber stelle.
-
Aber du willst das gleiche Verhalten wie ein Menü? Dann nimm ein Spy-Programm und guck welche Styles das Windows-Menüfenster gesetzt hat.
Ich denke es liegt an WS_EX_TOOLWINDOW.
-
Ich hab schon probiert mit einem Spyprogramm (Winspector) die Eigenschaften des Popup-Fensters herauszufinden, aber Popup-Fenster neigen leider dazu zu verschwinden, wenn man wegklickt

Irgendeine Idee wie ich das ausspionieren könnte?
-
LoL, jetzt hab ich rausgefunden wie das geht. Ich werd mir mal die Styles ansehen, und euch berichten ob ich das Problem gelöst habe oder nicht...
-
Manchmal passiert es das sich diese Popup-Menüs nicht richtig schließen. Diesen Bug habe ich ausgenutzt um es zu spyen.

WS_OVERLAPPED | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER
WS_EX_DLGMODALFRAME | WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR
Ich hatte das jetzt schon die ganze Zeit ausprobiert, aber ich kriege es nicht hin. Das Popup-Fenster klaut immer den Focus.
Früher hatte ich genau das selbe gewollt und ich glaub ich habe es auch hingekriegt, weiß aber nicht mehr genau wie.

Wenn du das irgendwie noch herausfinden solltest sag unbedingt in diesem Thread bescheid, ich will das auch wissen.

-
. schrieb:
Manchmal passiert es das sich diese Popup-Menüs nicht richtig schließen. Diesen Bug habe ich ausgenutzt um es zu spyen.

Den brauch ich nicht ausnutzen. Winspector hat ein besonderes Feature, mit dem man das problemlos spyen kann. Danke trotzdem.
Außerdem sag ich ganz bestimmt bescheid falls ich so ein richtiges Popup-Fenster hinkriege

-
Hab jetzt auch rausgefunden wie es mit Winspector funktioniert.

Ich hab jetzt nochmal über Google Groups gesucht und ein Hinweis auf "Fakemenu" bekommen.
Der Code ist sogar im Platform SDK vorhanden:
Microsoft Platform SDK\Samples\winui\Shell\Fakemenu
Ich werds mir nachher mal anschauen. Sieht aber gut aus.

-
. schrieb:
Hab jetzt auch rausgefunden wie es mit Winspector funktioniert.

Gratuliere

Für diejenigen, die es auch wissen wollen: Im Window Log-Fenster müsst ihr rechts auf das gewünschte Fenster klicken, und dann "Add window to watch..." wählen. Jedes mal wenn ein Fenster dieser Klasse erzeugt wird, zeigt Winspector das entsprechende Property- od. Message-Fenster.
. schrieb:
Ich hab jetzt nochmal über Google Groups gesucht und ein Hinweis auf "Fakemenu" bekommen.
Der Code ist sogar im Platform SDK vorhanden:
Microsoft Platform SDK\Samples\winui\Shell\Fakemenu
Ich werds mir nachher mal anschauen. Sieht aber gut aus.

Ich weiß schon wie man Popup-Fenster mit besagtem Verhalten programmieren kann. Ich hab aber nicht die Zeit, genau zu erklären wie. Als Stichwort nenn ich mal WM_NCACTIVATE und verweise Interessenten auf diese Seite: http://www.catch22.org.uk/tuts/docking1.asp ( Prevent window deactivation )
Und vielleicht kann noch jemand mit diesem Code etwas anfangen:
BOOL CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_INITDIALOG: return TRUE; case WM_ACTIVATE: switch( LOWORD(wParam) ) { case WA_ACTIVE: SendMessage(GetParent(hwndDlg), WM_NCACTIVATE, (WPARAM)TRUE, NULL); break; case WA_INACTIVE: DestroyWindow(hwndDlg); break; } return 0; case WM_ACTIVATEAPP: if( !wParam ) { SendMessage(GetParent(hwndDlg), WM_NCACTIVATE, (WPARAM)FALSE, NULL); DestroyWindow(hwndDlg); } return TRUE; case WM_COMMAND: switch( LOWORD(wParam) ) { case IDOK: case IDCANCEL: DestroyWindow(hwndDlg); return TRUE; } break; } return FALSE; }Der Code ist sehr spezifisch, d.h. er ist an meine Bedürfnisse angepasst, und enthält wahrscheinlich noch Bugs. Am besten ihr lest euch die Webseite durch, und versucht das Prinzip zu verstehen.
-
Wie ich befürchtet habe, ist der Code nicht optimal.
case WA_INACTIVE: DestroyWindow(hwndDlg); break;Die obigen Zeilen verursachen eine unendliche Schleife. Naja sie hört dann doch wieder irgendwann auf, aber erst beim ~25. Schleifendurchgang (beobachtbar mit Winspector). 'DestroyWindow' sendet anscheinend zusätzlich noch eine WM_ACTIVATE Message mit dem Wert WA_INACTIVE, was dann logischerweise dazu führt, dass DestroyWindow wieder aufgerufen wird.
Es gibt, wie ich herausgefunden habe, 3 Lösungsansätze:
.) Man verwendet einen lokalen Mousehook. Wenn der User einen Mausklick durchführt, prüft man ob der außerhalb des Dialoges war, wenn ja, dann zerstört man das Dialog-Fenster. (Vielleicht die sicherste Methode)
.) Man schickt mit PostMessage asynchron eine Message an sich selbst, welche wenn verarbeitet, das Fenster zerstört. Sprich:case WA_INACTIVE: PostMessage(hwndDlg, WM_COMMAND, IDOK, 0); //funktioniert bei mir soweit tadellos break;.) Wenn ihr Popup-Verhalten bei normalen Fenstern haben wollt, dann könnt ihr WM_KILLFOCUS abfangen und dort DestroyWindow aufrufen. Ob das Fenster diese Nachricht garantiert immer erhält weiß ich nicht. Dialog-Fenster erhalten diese Nachricht leider nicht.
-
Noch ein Nachtrag zur 2. Lösung:
In der Nachrichtenbehandlung von WM_ACTIVATEAPP muss eine Zeile entfernt werden.
case WM_ACTIVATEAPP: if( !wParam ) { SendMessage(GetParent(hwndDlg), WM_NCACTIVATE, (WPARAM)FALSE, NULL); //DestroyWindow(hwndDlg); //<- diese Zeile löschen } return TRUE;