Scrollbar vs WM_PAINT problem
-
Hallo,
ich habe ein problem mit der darstellung meiner Daten.
Ich habe ein Programm welches in unterschiedlichen zeitabständen Daten einliest und über wmpaint ausgibt.dabei habe ich das problem, dass wenn ich wmpaint neu zeichnen lasse die daten sich immer um eine zeile nach unten verschieben.
also ich habe das rect.top so verändert, dass die daten unterhalb meiner menuebar dargestellt werden. wenn ich jetzt jedoch einen wert einlese wird er unterhalb der bar angezeigt. soweit richtig. lese ich aber einen 2ten wert ein und stelle ihn dar, wird dieser unterhalb des ersten wertes angezeigt. jedoch rutschen beide daten dann um eine zeile nach unten.
muss ich das rect.bottom dann auch entsprechend verändern? ich hoffe ihr versteht mein problem

hier der code:
case WM_CREATE: g_hwndCB = CommandBar_Create(g_hInst, hWnd, 1); CommandBar_InsertMenubar(g_hwndCB, g_hInst, IDM_MENU, 0); CommandBar_AddAdornments(g_hwndCB, 0, 0); g_oScanner.registerLabelMessage(hWnd, WM_BARCODE_LABEL); g_oScanner.registerStartScanningMessage(hWnd, WM_SCANNER_START); g_oScanner.registerStopScanningMessage(hWnd, WM_SCANNER_STOP); g_oScanner.registerTimeOutMessage(hWnd, WM_SCANNER_TIMEOUT); break; case WM_SIZE: { HDC hDC; RECT TextRect; GetWindowRect(g_hwndCB, &rb); rect.left = iRand; rect.top = (rect.top + rb.bottom-rb.top); //0; rect.right = LOWORD(lParam) - iRand; rect.bottom = HIWORD(lParam); TextRect = rect; hDC = GetDC(hWnd); { DrawText(hDC, mystring, lstrlen(mystring), &TextRect, DT_WORDBREAK | DT_CALCRECT); } ReleaseDC(hWnd, hDC); iScrollRange = (TextRect.bottom - rect.bottom) / iZeichenhoehe + 1; iScrollPos = (iScrollRange < iScrollPos) ? iScrollRange : iScrollPos; SetScrollPos(hWnd, SB_VERT, iScrollPos, TRUE); SetScrollRange(hWnd, SB_VERT, 0, iScrollRange, TRUE); return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; GetWindowRect(g_hwndCB, &rb); rect.top = (rect.top + rb.bottom-rb.top); hDC = BeginPaint(hWnd, &ps); { DrawText(hDC, mystring, lstrlen(mystring), &rect, DT_WORDBREAK); } EndPaint(hWnd, &ps); return 0; } case WM_VSCROLL: { switch (LOWORD(wParam)) { case SB_LINEUP: iScrollPos = (iScrollPos > 0) ? (iScrollPos - 1) : 0; break; case SB_LINEDOWN: iScrollPos = (iScrollPos < iScrollRange) ? (iScrollPos + 1) : iScrollRange; break; case SB_PAGEUP: iScrollPos = 0; break; case SB_PAGEDOWN: iScrollPos = iScrollRange; break; case SB_THUMBPOSITION: iScrollPos = HIWORD(wParam); break; default: return 0; } SetScrollPos(hWnd, SB_VERT, iScrollPos, TRUE); rect.top = -iScrollPos * iZeichenhoehe; InvalidateRect(hWnd, NULL, TRUE); return 0; } ...Auch ohne neue Daten hinzuzufügen wird bei jedem neuzeichnen der datensatz um eine zeile nach unten versetzt.
wie kommt sowas ?

danke euch !!
-
Bitte versuche doch etwas mehr Windows Basics zu lernen! Was soll den der Code für DrawText in WM_SIZE.
In Fenstern sollte nur auf WM_PAINT Nachrichten hin gezeichnet werden!
-
also den beispielcode habe ich von der seite.
http://win-api.de/tutorials.php?tutid=16
daher eigentlich abgekupfert. soweit ich verstanden habe wird in wmsize nur die größe berechnet und dann mit wm_paint gezeichnet.
würdest du sagen das das überflüssig ist?
EDIT:
soweit hat es ja auch gut geklappt. nur das, wenn ich über wmpaint neu zeichne meine dargestellten codes immer um eine zeile nach unten rutschen. auch wenn ich den variableninhalt zur ausgabe nicht verändere.
-
1. Du rect static gemacht! Was glaubst Du was das bedeutet?
Die Daten beleiben erhalten.
2. Und was machst Du in WM_PAINT? Du erhöhst rect.top um die höe eines anderen Festers!
Die daten bleiben erhlaten.
3. Was glaubst Du was dies für Implikationen hat, wenn der WM_PAINT Code wieder durchlaufen wird?
Fang doch bitte mit etwas einfacherem an, dass Die auch mehr Verständnis für die Sprache C++ vermittelt.
-
ja es stimmt das es etwas zu viel fuer mich ist. aber ich habe diese aufgabe bekommen und möchte sie auch lösen. danach werde ich was einfacheres machen.
ich hoffe du hilfst mir trotzdem noch weiter. ich sitze schon so lange dran und stehe kurz vor dem ziel. da möchte ich nicht aufhören. es geht wirklich nur noch um die position des angezeigten textes und das funktionieren der scrollbar. wenn ich diese 2 sachen fertig habe ist es vollbracht
das mit der static deklarierung macht sinn. jedoch wird mir, wenn ich sie weg mache, gar nichts mehr angezeigt.
hier ist der code, so wie er "eigentlich" einwandfrei funktioniert.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; int cCount = 0; hWND = hWnd; hwn_D_thread = hWnd; TfillMsgPuffer(); static const int iRand = 65; static const int iZeichenhoehe = 18; static RECT rect; static RECT rb; static int iScrollRange; static int iScrollPos; switch (message) { case WM_CREATE: g_hwndCB = CommandBar_Create(g_hInst, hWnd, 1); CommandBar_InsertMenubar(g_hwndCB, g_hInst, IDM_MENU, 0); CommandBar_AddAdornments(g_hwndCB, 0, 0); g_oScanner.registerLabelMessage(hWnd, WM_BARCODE_LABEL); g_oScanner.registerStartScanningMessage(hWnd, WM_SCANNER_START); g_oScanner.registerStopScanningMessage(hWnd, WM_SCANNER_STOP); g_oScanner.registerTimeOutMessage(hWnd, WM_SCANNER_TIMEOUT); break; case WM_SIZE: { HDC hDC; RECT TextRect; GetWindowRect(g_hwndCB, &rb); rect.left = iRand; rect.top = 0; rect.right = LOWORD(lParam) - iRand; rect.bottom = HIWORD(lParam); TextRect = rect; hDC = GetDC(hWnd); { DrawText(hDC, mystring, lstrlen(mystring), &TextRect, DT_WORDBREAK | DT_CALCRECT); } ReleaseDC(hWnd, hDC); iScrollRange = (TextRect.bottom - rect.bottom) / iZeichenhoehe + 1; iScrollPos = (iScrollRange < iScrollPos) ? iScrollRange : iScrollPos; SetScrollPos(hWnd, SB_VERT, iScrollPos, TRUE); rect.top = -iScrollPos * iZeichenhoehe; SetScrollRange(hWnd, SB_VERT, 0, iScrollRange, TRUE); return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; GetWindowRect(g_hwndCB, &rb); hDC = BeginPaint(hWnd, &ps); { DrawText(hDC, mystring, lstrlen(mystring), &rect, DT_WORDBREAK); } EndPaint(hWnd, &ps); return 0; } case WM_VSCROLL: { switch (LOWORD(wParam)) { case SB_LINEUP: iScrollPos = (iScrollPos > 0) ? (iScrollPos - 1) : 0; break; case SB_LINEDOWN: iScrollPos = (iScrollPos < iScrollRange) ? (iScrollPos + 1) : iScrollRange; break; case SB_PAGEUP: iScrollPos = 0; break; case SB_PAGEDOWN: iScrollPos = iScrollRange; break; case SB_THUMBPOSITION: iScrollPos = HIWORD(wParam); break; default: return 0; } SetScrollPos(hWnd, SB_VERT, iScrollPos, TRUE); rect.top = -iScrollPos * iZeichenhoehe; InvalidateRect(hWnd, NULL, TRUE); return 0; } ...über den funktionsaufruf "TfillMsgPuffer();" wird die globale variable mystring neu gefüllt die ich dann über drawtext ausgeben möchte.
so wie es da steht funktioniert auch alles soweit. meine einzigen probleme sind, dass
- er unter der menuebar anfängt zu zeichnen und nicht weiter darunter
- und das, wenn ich scrolle ich mein rect.bottom vergrößern müsste.ich kann zwar wunderbar nach unten scrollen. mir fehlen unten aber immer so 1-2 zeilen die niht angezeigt werden.
sonst ist ales TOP

ich hoffe du verzeihst mir mein unwissen und zeigst gnade das ich zur ruhe komme ^^
ich wäre dir sehr sehr dankbar!!!!
EDIT:
also wenn ich rect.top auf rb.bottom setze dann werden die daten richtig dargestellt, also unterhalb der menuebar.
leider funktioniert dann aber die scrollbar nicht mehr. grml.. und ich weiss nicht warum !?!?
-
Mein letzter Tipp:
- Gib dem Scrollbar über SetScrollInfo etsprechenden Größen für maximale Ausgabelänge (= Texthöhe in Pixel), und die Setengröße (= Höhe dr Nutzbaren Client Area in Pixeln).
- Schreibe Deine WM_PAINT Routne so, dass immer alles einfach unterenandermit DrawText ausgegeben wird,beginnend ab Koordinate 0.
- Bevor Du eine Zeile ausgibst, besorgst Du Dir mit GetScrollInfo die Position des Rollbalkens. Diese Position setzt mit SetViewportOrg
- Im WM_VSCROLL Handler machst Du nur noch ein Invalidate der Client Area, den Rest regelt WM_PAINT.