Statusbar
-
Hallo, mit MoveWindow oder SetWindowPos flackert es genau so.
Hat jemand ein Beispiel für DoubleBuffering. SubClassing mach ich nicht.
-
Hopala, sry ich habe Status- mit Progressbar verwechselt. Ob das da mit DB funktioniert weiß ich net, Sorry.
Gruß Tobi.
-
Das hat nichts mit Double Buffering zu tun.
Ein anderes Fenster löscht beim neu Zeichnen des Hinterrundes eben auch dieses Control. Das flackert immer!Die Frage ist ob beim löschen des Mainframes auch der StatusBar neu gezeichnet wird! D.h. In diesem Fall dem Mainframe den Stil WS_CLIPCHILDREN geben!
Vermieden wird so etwas durch besseres Design der Fenster.
Mainframe enthält:
- Toolbar
- Statusbar
- Client Window (dieses Fenster nimmt den Rest ein)Die Folge das Mainframe hat keine eigene Client Area, die mehr gezeichnet werden muss. (So macht es die MFC)!
-
So ganz hab ich es nicht verstanden wie ich es anordnen soll.
Hast du ein kleines Beispiel für mich. Oder Link
-
Schau Dir die MFC an...
Nein! Aber was soll der Link? Du hast ein Mainframe und erzeugst darin Child Windows. Auch der verbliebende Bereich zwischen Toolbar und Statusbar wird durch ein Fenster belegt... Thats all...
-
Hi,
ich bin ich auch sehr an einer Lösung interessiert. Allerdings hatte ich diese Geschichte wegen anderer Prioritäten erstmal hintangestellt.In meinem Programm ist nämlich exakt das gleiche Flackerverhalten beim Größenändern zu beobachten wie bei MS Outlook 2003.
Um diese "Flacker-Prüfung" mal auf das einfachste zu reduzieren: Es genügt vollkommen, nur den unteren Fensterrand (und nicht die Fensterecke) zur Größenänderung des Fensters zu bewegen. Man sieht deutlich, daß selbst einfache Texte flackern. Evtl. mal genau hinschauen, es kann aber auch sein, daß das abhängig vom verwendeten Grafiktreiber und -chip ist.So habe ich also in meinem Programm zu Testzwecken die Icons und Bitmaps herausgenommen, daß nur noch Textausgaben in den einzelnen Statusbar-Feldern übrig bleiben. Das Flackern bleibt, wenn auch nicht mehr sooo deutlich. Beste Vergleichsreferenz dazu wäre die Statusbar von Hyperterminal (von Win XP SP2).
Folgende Programme haben (aus der Sicht der Nutzer) eine vorbildliche Implementation des Statusbars:
-MS Word 2003 und Excel 2003
-MS Internet Explorer 6 SP1 (naja, fast perfekt, der Size-Gripper selbst flackert schwach)
-IrfanView 4.10
-WordPad 5.1.2600 (von WinXP SP2)
-Notepad++ 4.2.2
Deshalb muß es eine Möglichkeit geben, die Statusbar perfekt flackerfrei hinzukriegenMartin Richter schrieb:
Vermieden wird so etwas durch besseres Design der Fenster. Mainframe enthält:
- Toolbar
- Statusbar
- Client Window (dieses Fenster nimmt den Rest ein)
Die Folge das Mainframe hat keine eigene Client Area, die mehr gezeichnet werden muss.Mein Programm habe ich auch genau so aufgebaut, trotzdem bleibt das gleiche Verhalten wie bei Outlook 2003. Sowohl der Text als auch der Size-Gripper an der Ecke flackern (wenn auch nur leicht).
Die Stile meiner Fenster sind wie folgt:
Mainframe hat den Stil WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
Statusbar hat den Stil WS_CHILD | SBARS_SIZEGRIP | WS_CLIPSIBLINGS
Die Child Windows haben den Stil WS_CHILD | WS_CLIPSIBLINGS und befinden sich im Bereich des Client-Areas von Mainframe abzüglich dem Bereich, den die Statusbar einnimmt.Ist vielleicht schon an meinen Fensterstilen ein Denkfehler unterlaufen?
Martin
-
Kleiner Nachtrag:
Martin Richter schrieb:
WM_SIZE gehört zu den Nachrichten, die nicht versendet werden dürfen sondern nur als Benachrichtigung dienen.
Führe SetWindowPos durch bzw. MoveWindow!Hmmm, das ist mir jetzt aber neu
Ich habe nämlich schon öfters gelesen, daß das Parent-Fenster an die Statusbar (Child-Fenster) die Nachricht WM_SIZE explizit weiterleiten muß.
Z.B. in der MSDN zu "Status Bars" http://msdn.microsoft.com/en-us/library/bb760728.aspx steht:
"The window procedure automatically adjusts the size of the status bar whenever it receives a WM_SIZE message. Typically, when the size of the parent window changes, the parent sends a WM_SIZE message to the status bar."In meiner Software habe ich nämlich genau so gemacht wie Dark77:
case WM_SIZE: SendMessage( hwnd_statusbar, WM_SIZE, (WPARAM)wParam, (LPARAM)lParam ); //Das Parent-Fenster muß an Statusbar (Child-Fenster) die Nachricht WM_SIZE explizit weiterleiten.
Ist dieses Weiterleiten von WM_SIZE vielleicht der Übeltäter für das Flackern der Statusbar?
Martin
-
Wenn ich nichts mache wird Stimmt die Größe meiner Statusbar beim Resize nicht
WM_SIZE weiterleiten, MoveWindow, SetWindowPos -> Flackern
-
Das liegt daran, dass Dein WM_ERASEBKGND wahrscheinlich eben Deinen Statusbar auch löscht. Das habe ich doch schon geschrieben.
-
Martin Richter schrieb:
Das liegt daran, dass Dein WM_ERASEBKGND wahrscheinlich eben Deinen Statusbar auch löscht. Das habe ich doch schon geschrieben.
Meinst Du
a) die WM_ERASEBKGND-Nachricht in der WndProc vom Mainframe?
Oder b) die (vermutete) automatische Verarbeitung von WM_ERASEBKGND im Status-Bar Control?Der Fall a) kann nach meinem Wissen nicht die Ursache sein, da für das Mainframe ja der Fensterstil WS_CLIPCHILDREN gesetzt ist. Also den Bereich des Statusbars als Child-Fenster ausgenommen. Oder gilt dieses Clippen etwa nur bei WM_PAINT-Nachrichten? Wenn ja, dann müßte ich bei WM_ERASEBKGND einen Rückgabewert ungleich 0 returnieren und selbst den Hintergrund im Clientbereich des Mainframe abzüglich des Statusbar-Bereichs neuzeichnen. Ist es so?
Für den Fall b) müßte ich theoretisch also den Statusbar-Control subclassen, um die WM_ERASEBKGND-Nachricht abfangen zu können?
Ich hoffe, daß Du uns mit Deinem Erfahrungsschatz weiterhelfen kannst. Für solche Probleme bräuchte ich idealerweise so etwas wie "Zeitlupen"-Verzögerer, um das Neuzeichnen der einzelnen Elemente detailliert beobachten zu können.
Martin
-
Hab jetzt mein Programm umgebaut.
Hab jetzt ein Hauptfenster.
Ein Kindfenster mit Buttons usw
Und die StatusbarDas zeug flackert aber noch. Kann mir jemand die Styles der Fenster sagen, die ich setzen muss.
Sieht so aus:
WNDCLASS wc; RECT rect; hInst = (HINSTANCE)hInstance; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = (HINSTANCE)hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1) ; //(COLOR_APPWORKSPACE+1); wc.lpszMenuName = NULL wc.lpszClassName = "MAINCLASS"; RegisterClass(&wc); /* create main window */ hWndMain = CreateWindowEx( WS_EX_CONTROLPARENT | WS_EX_ACCEPTFILES, "MAINCLASS", /* main window class */ "Mein Fenster", /* window title */ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* window style */ CW_USEDEFAULT, /* default horizontal position */ CW_USEDEFAULT, /* default vertical position */ CW_USEDEFAULT, /* default width */ CW_USEDEFAULT, /* default height */ HWND_DESKTOP, /* overlapped windows have no parent */ NULL, /* use the window class menu */ (HINSTANCE)hInstance, /* this instance owns this window */ NULL /* pointer not needed */ ); GetClientRect(hWndMain, &rect); wc.hIcon = NULL; wc.lpfnWndProc = ChildWndProc; wc.lpszClassName = "CLIENTCLASS"; RegisterClass(&wc); priv->hWndClient = CreateWindow("CLIENTCLASS", NULL, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | WS_DLGFRAME, 0, 0, rect.right, rect.bottom, hWndMain, NULL, (HINSTANCE)hInstance, NULL); hWndStatus = CreateWindowEx(0, STATUSCLASSNAME, "", WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, 0, 0, 0, 0, hWndMain, (HMENU)1, hInst, NULL);
-
Gut! Dein Mainframe benutzt WS_CLIPCHILDREN. Bist Du auch sicher, dass das Clientfenster mit dem Statusbar nicht überlappt.
BTW: WS_CLIPCHILDREN macht für die Kindfenster selber gar keinen Sinn!
-
-click @ home
-
Martin Richter schrieb:
Das liegt daran, dass Dein WM_ERASEBKGND wahrscheinlich eben Deinen Statusbar auch löscht. Das habe ich doch schon geschrieben.
Nun, ich habe meine Applikation testweise bei WM_ERASEBKGND mit Rückgabewert 1 returniert.
Es ist kein Unterschied feststellbar, d.h. die Felder in der Statusbar flackern immer noch. Dafür ist natürlich der Hintergrund des Frame-Fensters "undefiniert"Martin Richter schrieb:
WM_SIZE gehört zu den Nachrichten, die nicht versendet werden dürfen sondern nur als Benachrichtigung dienen.
Führe SetWindowPos durch bzw. MoveWindow!
Ich werde mal am Wochenende daheim Deinen Vorschlag mit SetWindowPos bzw. MoveWindow ausprobieren.
Um den Lerneffekt zu erhöhen:
Warum darf man WM_SIZE nicht versenden? In der MSDN ist (speziell für Statusbar) das Gegenteil zu lesen, siehe mein Posting vom 09.05.2008 weiter oben. Oder habe ich diesen (fett markierten) Satz völlig mißverstanden?Martin
-
Mmacher schrieb:
Um den Lerneffekt zu erhöhen:
Warum darf man WM_SIZE nicht versenden? In der MSDN ist (speziell für Statusbar) das Gegenteil zu lesen, siehe mein Posting vom 09.05.2008 weiter oben. Oder habe ich diesen (fett markierten) Satz völlig mißverstanden?Es gibt Fensternachrichten, die entstehen durch bestimmte API Funktionen: WM_SETFOCUS, WM_PAINT, WM_ERASEBKGND, WM_SIZE etc.
Diese Funktionen sind Benachrichtigungen, die natürich nur Sinn machen, wenn die entsprechende Funktion auch ausgelöst wurde. Umgekehrt kann en Programm ziemlich durcheinander kommen, wenn es meint, dass etwas bstimmtes geschehen ist (WM_SETFOCUS==hat den Focus bekommen), aber das stimmt evt. gar nicht...