Text aus Textfile auf OwnerDraw-Button


  • Mod

    Ich würde Dir enfach mal raten ein wenig mehr Grundlagen zu lernen.
    Oder auf die Hinweise zu achten, die Du bereits bekommen hast.
    1. In OnPint ein WM_SETFONT zu senden führt dazu, dass das Control immer wieder neu gezeichnet wird.
    2. Führt WM_SETFONT nicht dazu, dass ein Zeichenvorgang mit DrawText auch diesen Font verwendet.
    3. Ein Anderer Poster hat Dich bereits auf SeelectObject hingewiesen.

    Also wie mach man es richtig?

    1. WM_SETFONT wird enmal von außen an ein Control geschickt. Sofern das Control in einem Dialogliegt musst Du nichts machen.
    2. Um einen Font anzuwenden, sendet man an sich selbst WM_GETFONT und nimmt dieses Handle für SelectObject und zeichnet dann den Text.
    3. Man lässt in OnPint dir Finger von allem, was ein Repaint auslösen könnte, wie WM_SETFONT, InvalidateRect, MoveWindow, SetWindowPos etc.

    HTH



  • Ja Martin, Du hast ja Recht mit der Aussage, dass mir noch ne Menge an Grundlagen fehlen... 😞

    Ich arbeite ja auch daran, mir diese anzueignen!

    Das mit OnPaint() hatte ich schon gedacht und das DrawText schon verlegt. Das war Dummheit vorm Feind. 👎

    Nur kriege ich einfach keinen Kopf daran, mit SelectObject(... Hab ich noch nie benutzt... Überhaupt mit DrawText noch nie vorher 😞

    Edit:
    Ich hab es hinbekommen!!!

    Danke für die Hilfe... irgendwie stachelt einen doch irgendwie an, nochmal alle Gehirnzellen zu aktivieren, wenn man mal wieder eins auf die Ohren bekommt!



  • Neue Problemstellung:

    Hab jede Menge gelesen und auch den Ausschluss von DT_WORDBREAK mit DT_VCENTER gelesen...
    Gibt es trotzdem eine Lösung, dass man 2-zeiligen Text center auf den Button bekommt???

    SetRect(&rc, 50, 0, 239, 0); //50px von links wegen Icon, 239 Breite des Buttons
    
    	/* ermittle die Breite des Textes und mache wenn nötig ein Wordbreak */
    	DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_WORDBREAK | DT_CALCRECT);
    
    	/* Zeichne den Text auf den Button */
    	DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc,  DT_LEFT | DT_VCENTER );
    


  • Du kannst dir ja das benötigte Rect von DrawText berechnen lassen. Dieses must du dan halt selber entsprechend vertikal versetzen, so das es in der Mitte ist.



  • Klar, das könnte ich machen, wenn ich die Buttongrösse festlegen würde.
    Diese wird aber über die Steuerdatei ausgelesen. Der User kann sich die Buttongrösse selber anpassen, bzw. ist diese abhängig von der Screen-Grösse.

    ...oder denke ich gerade zu kompliziert??? 😕

    Edit:

    SetRect() holt sich die Buttongrösse:

    SetRect(&rc, 50, 0, bm.bmWidth-0, bm.bmHeight-0);
    

  • Mod

    Ich verstehe überhaupt nicht, was Du hier sagst!

    Wenn Du zeichnest steht doch die Button Größe fest oder?
    Und die ermittelst Du mit GetClientRect.

    Also:
    - DrawText mit DT_CALCRECT benutzen um die Größe zu ermitteln.
    - Dan Koordinaten errechnen anhand GetClientRect
    - Dann Zeichen...



  • Du liest die Koordinaten aus der Datei und hälst sie doch im Speicher, oder?

    Andernfalls kannst du auch mit GetWindowRect jederzeit die Größe der Buttons beim Zeichnen abfragen und den Text zentriert malen.



  • hmmm...
    Sorry, wenn ich viel doofes Zeug frage, aber ich bin halt immer noch Anfänger... 😞

    Glaubt mir... wenn ich wüsste, wie ich das berechnen könnte, würde ich bestimmt nicht fragen. Bin niemand, der sich mit Vielposterei auszeichnen will.

    Wenn ich das also richtig verstehe, dann habe ich mit:
    bm.bmWidth und bm.bmHeight schon mal die Button-Größe, soweit ist das klar.

    DT_CALCRECT ermittelt nun die Höhe der Gesamtschrift, wenn ich vorher mit DT_WORDBREAK den Zeilenumbruch aktiviere.

    OK, nun kommt das für mich, wo ich nicht weiss, wie ich das Ergebnis von DT_CALCRECT nun auslesen kann?!?

    Das Berechnen selber ist ja nicht das Problem:
    Versatz nach unten = (Buttonhöhe - Ergebnis aus CALCRECT)/2

    ...oder ist das alles Unfug???



  • rectBtn = GetClientRect()
    rectTxt = DrawText(...,DT_CALCRECT)

    y = rectBtn.top+(rectBtn.bottom-rectBtn.top)/2 - (rectTxt.bottom-rectTxt.top)/2



  • Vielleicht bin ich zu blööd dafür... Versteh gerade nur Bahnhof und Kofferklauen... 😞



  • Du hast zwei Rechtecke, gegeben durch jeweils zwei Punkte, von denen das eine im anderen vertikal zentriert werden soll ... mal es dir halt mal auf ein Blatt Papier auf.



  • Das mit der Berechnung an sich ist mir klar...

    Warum brauche ich GetClientRect()? Da brauche ich ein Fensterhandle,wobei ich verschiedene Button-Grössen habe... Kann ja sein, dass ich in der Gesamt-Struktur da schon Mist gebaut habe, aber jeder Button hat ein eigenes Fensterhandle.

    Die Grösse des Buttons hab ich doch schon über bm.bmWidth und bm.bmHeight.

    Was ich nicht verstehe, wie ich das Ergebnis aus y dann übergebe.... und da hänge ich am Fliegenfänger...



  • im welchem Teil deines cods Zeichnest du den den Text? Und warum hast den dann kein Handle? - das ergibt keinen Sinn.



  • Die Buttons an sich werden im OnCreate()gesetzt:

    /***********Reihe 1***************/
    	if (_wfopen(buttons[0].link , L"r") != 0){		// prüft ob die auszuführende Exe vorhanden ist. Falls nicht, wird der Button nicht angezeigt.
    		hWndBtn0 = CreateWindow( L"BUTTON", L"Button 1", WS_VISIBLE | BS_OWNERDRAW, 0, 33, 239, 62, hwnd, (HMENU)(IDM_BTN1+0), hInst, NULL); 	
    		hBM[0] = SHLoadDIBitmap(buttons[0].pic);
    	}
    	if (_wfopen(buttons[1].link , L"r") != 0){
    		hWndBtn1 = CreateWindow( L"BUTTON", L"Button 2", WS_VISIBLE | BS_OWNERDRAW, 241, 33, 239, 62, hwnd, (HMENU)(IDM_BTN1+1), hInst, NULL); 
    		hBM[1] = SHLoadDIBitmap(buttons[1].pic);
    	}
    

    In dieser Testversion wird die Buttongrösse noch fix gesetzt, allerdings soll die demnächst aus der Steuerdatei kommen...

    Die Bitmaps und der Text werden dann im OnDrawItem() gezeichnet:

    void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)
    {
    	RECT rc;
    	HDC hdc;
    	HDC hdcMem;
    	HBITMAP hBM0;
    	BITMAP bm;
    	int nIdx;
    
    	if (lpDrawItem->CtlID < IDM_BTN1 || lpDrawItem->CtlID > (IDM_BTN1+BUTTONMAX))
    		return;
    
    	nIdx = lpDrawItem->CtlID-IDM_BTN1;
    	rc = lpDrawItem->rcItem;
    	hdc = lpDrawItem->hDC;
    	hBM0 = hBM[nIdx];
    	hdcMem = CreateCompatibleDC(hdc);
    	SelectObject(hdcMem, hBM0);
    	GetObject(hBM0, sizeof(bm), &bm);
    	if (lpDrawItem->itemState & ODS_SELECTED) {									//  wenn geklickt wurde.
    		BitBlt(hdc, -2, -2, bm.bmWidth-0, bm.bmHeight-0, hdcMem, -2, -2, SRCCOPY);	// zeichnet den Button
    		DrawEdge(lpDrawItem->hDC, &rc, EDGE_SUNKEN, BF_TOPLEFT);			// 3-D-Anzeige, wenn geklickt
    	}
    	else {
    		BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);			// ungeklickter Button
    	}
    	SetBkColor (hdc, TRANSPARENT); 
    	SetBkMode(hdc, TRANSPARENT); 
    	SetTextColor(hdc, RGB(255,255,255));
    	SetRect(&rc, 50, 0, bm.bmWidth, bm.bmHeight);
    
    	/* draw the text on the button */
    
    	DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_WORDBREAK | DT_CALCRECT); // DT_WORDBREAK
    	DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_WORDBREAK | DT_LEFT); //DT_VCENTER );
    
    	DeleteDC(hdcMem);
    }
    

    so sieht das bei mir jetzt aus...



  • arbeite dich doch bitte erstmals durch ein WinAPI-Tutorial durch! - so ist das nur ein Rumpfuscherei.
    und im Übrigen zum Thema button-Handle:

    void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)



  • Dann erst mal Danke für den Hilfeversuch. 👍

    Mal sehen, wie ich das hin bekomme...



  • Nur mal als Rückmeldung:

    Ich brauche kein GetClientRect() Das hat mich die ganze Zeit verwirrt...

    RECT rc, rcT;
    
    /* hier zwischen werden die Bitmaps auf die Buttons gezeichnet */
    
    	SetRect(&rc, 50, 0, bm.bmWidth, bm.bmHeight);
    
    	if (lstrlen(buttons[nIdx].text) > 3){      // Zeichnet Text nur, wenn mehr als 3 Zeichen
    	 	rcT.bottom = DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rc, DT_WORDBREAK | DT_CALCRECT | DT_LEFT | DT_EXPANDTABS | DT_NOPREFIX);
    
    		int textHeight = (bm.bmHeight/2 - rc.bottom/2);
    		SetRect(&rcT, 50, textHeight, bm.bmWidth, bm.bmHeight);
    		DrawText(lpDrawItem->hDC, buttons[nIdx].text, lstrlen(buttons[nIdx].text), &rcT, DT_WORDBREAK | DT_LEFT);
    	}
    

  • Mod

    Pitter (c) schrieb:

    Nur mal als Rückmeldung:

    Ich brauche kein GetClientRect() Das hat mich die ganze Zeit verwirrt...

    Du hast eigentlich noch gar nichtsverstanden!
    Dein ClientRect ist das sichtbare Areal von Deinem Cntrol.
    Wenn Du einen vernünftigen WM_PAINT Handler baust benötigst Du es immer!

    Was machst Du denn, wenn Dein Control von außen neu gezeichnet wird?
    Dein Weg auf irgendwelchen Font oder Bitmap Größen Annahmen zu machen ist falsch!

    Lies ein Tutorial...


Anmelden zum Antworten