Dieser Rand um die Buttons



  • Hallo,

    ich habe ein kleines Problem, dass ich einfach nicht gelöst bekomme.
    Ich habe keinen normalen Button, sondern ein Button wo eine Bitmap drauf gelegt ist

    // Bitmap laden aus Datei. Mit GetModuleHandle (NULL) wird die HINSTANCE geholt.
       		hBitmap = LoadImage (GetModuleHandle (NULL), "Buttons\\Button4.3.bmp",
          	IMAGE_BITMAP,0, 0,LR_DEFAULTCOLOR | LR_LOADFROMFILE);
    
    		// Jetzt wird ein Button erzeugt. hwnd ist das Handle zum Hauptfenster.
    	   hButton = CreateWindow("BUTTON", "", WS_VISIBLE|WS_CHILD|BS_BITMAP|BS_FLAT|BS_PUSHBUTTON,
                              20, 525, 400, 69,
    						  hwnd, (HMENU) ID_BUTTON, NULL, NULL);
    
    		//Das Bitmap auf den Button plazieren
    	   SendMessage (hButton, BM_SETIMAGE, (WPARAM) IMAGE_BITMAP,(LPARAM)(HANDLE) hBitmap);
    		  CreateWindow(TEXT("button"), TEXT(""),
    			     WS_VISIBLE | WS_CHILD,
    			     0, 0, 0, 0,
    			     hwnd, (HMENU) ID_BUTTON, NULL, NULL);
    

    aber jetzt ist da immer so ein weißer rand um den Button. Wie bekomme ich den da weg?

    Ich hoffe ihr könnt mir helfen (bin leider noch ein Anfänger, also möglichst unkompliziert)

    MFG
    Aaron



  • Für mich nicht wirklich nachvollziehbar, da nicht reproduzierbar. Bei mir befindet sich ein schmaler schwarzer (bzw. dunkelgrauer) Rand um den Button. Sollten wir jetzt - trotz Farbunterschied - vom gleichen Rand sprechen, dann muss ich dich insofern enttäuschen, als dass es keine "unkomplizierte" Lösung gibt.
    Um diesen Rand wegzubekommen, hilft nur selbstzeichnen. Stichworte sind "button ownerdraw winapi" bzw. "BS_OWNERDRAW" und "WM_DRAWITEM". Da findet sich direkt als Erstes dieser Link beim allmächtigen Google: http://www.codeproject.com/Articles/19913/Owner-draw-icon-buttons-in-plain-C-no-MFC

    Wirklich schwierig ist das Selbstzeichnen im Übrigen nicht, sind nur ein paar kleine Schritte mehr, die gemacht werden müssen. Dafür hast du aber mehr Freiheiten.



  • Mmmh ich habe es mir durchgelesen. Teile habe ich auch verstanden. Aber lange noch nicht alles.

    Könntest du vllt. ein kleines Beispiel machen?



  • Nein. Wo genau ist dein Problem? Bzw. was verstehst du nicht?
    Ohne Eigeninitiative zu sehen (allein die Bekundung, es gelesen zu haben, zählt nicht), werde ich sicher kein fertiges Beispiel posten.

    Poste deine Versuche und daran wird dir dann geholfen.



  • Mmmh.

    Ich glaube ich brauch das alles gar nicht machen. Ich habe herausgefunden, dass das Fenster meines Buttons eine andere Farbe hat wie die Bitmap.
    Also stelle ich mir die Frage, wie man die Farbe des Fensters eines Buttons verändert. Oder geht das gar nicht?

    Vllt. ja so:

    HBRUSH CTestColorButtonDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
    {
            HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
            if ( nCtlColor==CTLCOLOR_BTN) 
            {
                    if (pWnd == &m_MyButton)
                            return CreateSolidBrush(RGB(255,0,0));
            }
            return hbr;
    }
    

    Würde das vllt. funktionieren?



  • Aaron3219 schrieb:

    Also stelle ich mir die Frage, wie man die Farbe des Fensters eines Buttons verändert. Oder geht das gar nicht?

    Nee, sowas hab ich noch niiiieee gesehen 😃

    Sind wir noch bei WinAPI oder nun bei MFC ?

    Wenn es WinAPI sein soll könnte WM_CTLCOLORBTN wohl in Frage kommen. Das funktioniert aber m.E.
    nur bei owner-drawn Buttons, wobei BS_BITMAP und BS_OWNERDRAW nicht gleichzeitig geht.

    Auch sollten Pinsel und Schriften nur einmal erstellt werden und beim
    Schlissen des Fensters auch wieder gelöscht werden.

    static HBRUSH hbr=NULL;
    ...
    case WM_CREATE: {
       // Jetzt wird ein Button erzeugt. hwnd ist das Handle zum Hauptfenster.
       HWND hButton = CreateWindow(_T("BUTTON"), _T(""),
            WS_VISIBLE|WS_CHILD|BS_FLAT|BS_PUSHBUTTON| BS_OWNERDRAW,
            20, 525, 400, 69, hWnd, (HMENU) IDC_BUTTON1, NULL, NULL);
    
       // Background Brush
       hbr = CreateSolidBrush(RGB(255, 0, 255));
       }
       break;
    
    case WM_CTLCOLORBTN:
      return (LRESULT)hbr;
    


  • Danke, so hat es funktioniert. Natürlich musste ich noch "gdi32" einfügen

    static HBRUSH hbr=NULL;
    case WM_CREATE: {
    
       HWND hButton = CreateWindow(_T("BUTTON"), _T(""),
            WS_VISIBLE|WS_CHILD|BS_FLAT|BS_PUSHBUTTON| BS_OWNERDRAW,
            20, 525, 400, 69, hwnd, (HMENU) IDC_BUTTON, NULL, NULL);
    
       hbr = CreateSolidBrush(RGB(255, 0, 255));
       }
       break;
    
    case WM_CTLCOLORBTN:
      return (LRESULT)hbr;
    

    Vielen dankt merano!!!

    Allerdings habe ich noch eine Frage. Wie bekomme ich jetzt die Bitmap ins Bild?



  • Die Bemerkung mit gdi32 verstehe ich zwar nicht, aber wenns hilft ...

    Ist Dein "Goggle" kaputt ?

    Na ja, siehe hier:

    drawing on pushbutton with bitblt
    http://forums.codeguru.com/showthread.php?407939-drawing-on-pushbutton-with-bitblt



  • Ich hab mir das alles durchgelesen und habe mich daran probiert. Auch habe ich alnge rumgegoogelt, aber ich krieg es einfach nicht auf die Reihe.
    Ich bitte nun doch nochmal ein Beispiel zu machen.
    Also es sieht so aus

    static HBRUSH hbr=NULL;
    case WM_CREATE: {
    
       HWND hButton = CreateWindow(_T("BUTTON"), _T(""),
            WS_VISIBLE|WS_CHILD|BS_FLAT|BS_PUSHBUTTON| BS_OWNERDRAW,
            20, 525, 400, 69, hwnd, (HMENU) IDC_BUTTON, NULL, NULL);
    
       hbr = CreateSolidBrush(RGB(255, 0, 255));
       }
       break;
    
    case WM_CTLCOLORBTN:
      return (LRESULT)hbr;
    

    Im Programm sieht das so aus:

    _________________
    ||
    |
    |
    ||
    |_farbige Fläche_____|
    |
    (ohne_Rand)____|
    |
    |
    |
    |
    |
    ___|

    Wäre echt nett wenn jemand mal ein Beispiel macht. Ich komme so nicht weiter.





  • Der Compiler sagt mir jetzt noch,

    In function 'LRESULT WndProc(HWND, UINT, WPARAM, LPARAM)':|
    error: 'pdis' was not declared in this scope|
    error: 'rapo1' was not declared in this scope|
    error: 'rapo2' was not declared in this scope|
    ||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
    


  • Aaron3219 schrieb:

    Der Compiler sagt mir jetzt noch, ...

    In function 'LRESULT WndProc(HWND, UINT, WPARAM, LPARAM)':|
    error: 'pdis' was not declared in this scope|
    error: 'rapo1' was not declared in this scope|
    error: 'rapo2' was not declared in this scope|
    ||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
    

    Ist Dir das eigentlich nicht peinlich ?

    Ja, klar nicht deklarierte Variablen mit zugegeben seltsamen Namen ...

    Üblicherweise wird etwas Eigenleistung erwartet, und zum Abschluss als Feedback eine funktionierende Lösung
    vom Fragesteller.

    Es sollte eigentlich so sein, das sich der Fragesteller soweit damit befasst, das er zum Schluss
    weiss was da passiert.

    Diese Chancen hast Du nun bisher leider alle verpasst ...

    Um hier mal zum Schluss zu kommen nun alles "am Stück".

    static HWND hButton;
    static HBITMAP hBitmap=NULL;
    static BITMAP bmpbut;
    static HBRUSH hbr=NULL;
    
    switch (message)
    {
    case WM_CREATE: {
      hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), _T("Button4.3.bmp"),
    	                       IMAGE_BITMAP,0, 0,LR_DEFAULTCOLOR | LR_LOADFROMFILE);
    
      GetObject(hBitmap, sizeof(BITMAP), &bmpbut);
    
      hButton = CreateWindow(_T("BUTTON"), _T("Test"), WS_VISIBLE|WS_CHILD|BS_FLAT|BS_PUSHBUTTON|BS_OWNERDRAW, 
                             20, 20, bmpbut.bmWidth+2, bmpbut.bmHeight+2, hWnd, (HMENU)IDC_BUTTON1, NULL, NULL);
    
      // Bitmap auf Button plazieren (nur bei BS_BITMAP)
      // SendMessage (hButton, BM_SETIMAGE, (WPARAM) IMAGE_BITMAP,(LPARAM)(HANDLE) hBitmap);
    
      hbr = CreateSolidBrush(RGB(255, 0, 255)); 	   // Background Brush
      }
      break;
    
    case WM_DRAWITEM: {
      LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT) lParam;
      switch (pdis->CtlID){
         case IDC_BUTTON1:
              HDC hDC = GetDC(hButton); 
              HDC hComDC = CreateCompatibleDC(hDC); 
              SelectObject(hComDC, hBitmap); 
              BitBlt(hDC, 1, 1, bmpbut.bmWidth, bmpbut.bmHeight, hComDC, 0, 0, SRCCOPY); 
              DeleteObject(hComDC);
              ReleaseDC(hButton, hDC);
              break;
    
              // case XXXX: // Hier evtl. weitere Buttons
              //      break;
        }
    
        if(pdis->itemState & ODS_SELECTED) 
           InvertRect (pdis->hDC, &pdis->rcItem); // wenn Button gedrückt invertieren
      }
      break;
    
    case WM_CTLCOLORBTN:
      return (LRESULT)hbr; 
    
    ...
    

    Fehlerabfragen und das Freigeben der unter WM_CREATE angeforderten Resourcen sind nicht dabei ...



  • In dem Link, den ich angegeben habe, wird gesagt, dass man die Bitmap nicht auf den Button blitten sollte, weil dann wieder ein Rand drumherum bleibt.
    Stattdessen sollte man die Bitmap ins Parentfenster des Buttons blitten ...

    Ich habs selbst nicht ausprobiert.



  • Belli schrieb:

    Ich habs selbst nicht ausprobiert.

    Solltest Du vielleicht mal.

    Habs ausprobiert und dieses Problem nicht gesehen, aber auch nicht umfassend danach gesucht ...



  • Wenn man ohnehin GDI+ verwendet kann man die Laderoutine noch verbessern um z.B. auch jpg oder png anzeigen zu können:

    HBITMAP LoadImg(WCHAR *szFilename)
    {
       HBITMAP result=NULL;
    
       Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(szFilename,false);
       bitmap->GetHBITMAP(NULL, &result);
       delete bitmap;
       return result;
    }
    


  • Mmmh ich habe das Problem auch nicht gesehen.

    Es hat funktioniert.
    Vielen dank merano.

    LG Aaron


Log in to reply