Hintergrund Textfeld ändern



  • Ein einfaches Beispiel, bei jedem Betätigen des Knopfes wechselt das Editfeld seine Hintergrundfarbe:

    #include <windows.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         HWND     hwnd; 
         MSG      msg;
         WNDCLASS wndclass;
    
         wndclass.style         = CS_HREDRAW | CS_VREDRAW;
         wndclass.lpfnWndProc   = WndProc;
         wndclass.cbClsExtra    = 0;
         wndclass.cbWndExtra    = 0;
         wndclass.hInstance     = hInstance;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
    	  wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
         wndclass.lpszMenuName  = NULL;
         wndclass.lpszClassName = "FensterKlasse";
    
         RegisterClass (&wndclass);
    
         //Ein einfaches Fenster erstellen
         hwnd = CreateWindow ("FensterKlasse", "Fenster",
                              WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              200, 100,
                              NULL, NULL, hInstance, NULL);
         ShowWindow (hwnd, iCmdShow);
         UpdateWindow (hwnd); 
    
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg);
              DispatchMessage (&msg);
         }
         return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        //Zwei Brushes für zwei verschiedene Hintergrundfarben
        static HBRUSH brush0 = CreateSolidBrush(RGB(255, 0, 0));
        static HBRUSH brush1 = CreateSolidBrush(RGB(0, 255, 0));
    
        //ein Editfeld
        static HWND editFeld;
    
        //Status der Hintergrundfarbe, kann 0 oder 1 annehmen
    	 static int brushNr = 0;
    
         switch (message)
         {
         case WM_CREATE :
    
         		 //ein Editfeld mit dem Attribut WS_DISABLED erstellen
              editFeld = CreateWindowEx (WS_EX_CLIENTEDGE, "edit", NULL,
    			  WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_LEFT,
                             3, 3, 80, 20, hwnd, (HMENU) 1,
                             ((LPCREATESTRUCT) lParam) -> hInstance, NULL);
    
              //Einen Button erstellen
    		    CreateWindow ("button", "Knopp",
                             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                             3, 33, 80, 20, hwnd, (HMENU) 2,
                             ((LPCREATESTRUCT) lParam) -> hInstance, NULL);
    
              return 0;
    
         case WM_CTLCOLORSTATIC: 
              //Hintergrundfarbe für das disabled Editfeld abhängig vom Status der Hintergrundfarbe zurückgeben
              if(brushNr)
                return (LRESULT)brush1;
              else
                return (LRESULT)brush0;
    
         case WM_COMMAND :
              //Auf Knopfdruck den Status der Hintergrundfarbe toggeln
              brushNr = !brushNr;
              //Neuzeichnen des Editfeldes veranlassen
    			 InvalidateRect(editFeld, 0, TRUE);
    
              return 0;
    
         case WM_DESTROY :
         		 DeleteObject(brush0);
         		 DeleteObject(brush1);
              PostQuitMessage (0);
              return 0;
         }
         return DefWindowProc (hwnd, message, wParam, lParam);
    }
    


  • Hi,

    vielen Dank für Dein ausführliches Beispiel. Allerdings funktioniert es immer noch nicht; ich habe noch einmal eine Messagebox eingebaut, wenn das WM_CTLCOLORSTATIC aufgerufen wird. Allerdings wird die auch nicht gezeigt. In meiner Entwicklungsumgebung Watcom unter WinXP für ein 16bit Programm für Win 3.11 (fragt nicht!!!) kennt er das WM_CTLCOLORSTATIC auch nicht, so dass ich hier den Wert 0x0138 definieren musste. Aber liegt es wirklich an der Umgebung?

    MfG, Ozzy



  • Ich stelle gerade selbst erstaunt fest, dass mein Beispielprogramm unter WinXP erstellt mit VS 2010 einwandfrei läuft, unter Win7 aber nicht.
    Weder die exe, die unter XP läuft, noch eine unter Win7 aus dem geposteten Quelltext mit VS 2012 erstellte Version ...

    Das Programm läuft zwar, aber von dem disableten Editfeld wird nur ganz rechts und links am Rand eine dünne Linie wie gewünscht gefärbt.

    Eine Erklärung dafür habe ich leider nicht ... 😕



  • Hi,

    aber bei Dir wird das WM_CTLCOLORSTATIC wenigstens aufgerufen, oder?



  • Wie gesagt, unter XP läuft es einwandfrei. Unter Win7 gehe ich davon aus, dass die Message kommt, weil ich am rechten und linken Rand des Edit-Controls den gewünschten Effekt sehe.

    Läuft das Beispiel bei Dir unter XP etwa auch nicht? Oder hast Du keine Möglichkeit, es auf XP zu testen?



  • Also: ich habe unter meinem Win7 64-Bit den Windows Virtual PC laufen (XP-Mode). Hier verwende ich den Watcom compiler. Ist also alles etwas kompliziert...



  • Ich habe es in einem virtuellen XP (VMWare) auf Win7 64 mit VS 2010 erstellt, da läuft es einwandfrei.
    Auf dem Win7 leider nicht, und ich hab keine Ahnung, warum nicht 😕



  • Belli schrieb:

    Ich habe es in einem virtuellen XP (VMWare) auf Win7 64 mit VS 2010 erstellt, da läuft es einwandfrei.
    Auf dem Win7 leider nicht, und ich hab keine Ahnung, warum nicht 😕

    Naja, unter läuft einwandfrei verstehe ich was anderes ...

    Hab das Programm gerade unter XP getestet - das Editfeld wird auch hier nur
    eingefärbt, solange das Feld mit WS_DISABLED nicht editierbar ist.

    Wenn man mit SetWindowText(editFeld, "test") einen Text reinschreibt hat dieser einen weissen Hintergrund.

    Wenn man das Flag WS_DISABLED weglässt ist der Text editierbar, der Hintergrund aber nicht in der
    gewünschten Farbe - egal wie of man den Knopf drückt.

    Setzt man einen Breakpoint auf WM_CTLCOLORSTATIC wird dieser nicht ausgelöst.

    Verbesserungsvorschlag:

    Die Message WM_CTLCOLORSTATIC wird nur bei readonly edit controls angesprungen -ansonsten WM_CTLCOLOREDIT.

    Die Textfarbe sollte sich von der Hintergrundfarbe unterscheiden und Text sollte mit transparenter
    Hintergrundfarbe geschrieben werden.

    Das könnte insgesammt so aussehen:

    case WM_CTLCOLOREDIT:     
     case WM_CTLCOLORSTATIC: {
               if((HWND)lParam == editFeld) {
                  HDC hdcStatic = (HDC)wParam;
                  SetTextColor(hdcStatic, RGB(0, 0, 0));
                  SetBkMode(hdcStatic, TRANSPARENT);
    
                  if(brushNr)
                      	return (LRESULT)brush1; 
    	     else 
                      	return (LRESULT)brush0; 
    			 }
                  return (INT_PTR)GetStockObject(WHITE_BRUSH);
    	  }
    

    Auch die Kommentare unter

    http://msdn.microsoft.com/de-de/library/windows/desktop/bb787524(v=vs.85).aspx

    geben weitere Verbesserungsvorschläge ...

    // (as an aside, you should call DefWindowProc here)
    SetDCBrushColor(hdc, 0xFF00FF);         // select some color into the DC brush
    return (LPARAM)GetStockBrush(DC_BRUSH); // return the DC brush -- no need to release it!
    


  • Natürlich wird es nur eingefärbt, solange es disabled ist, darum geht es hier ja. Für ein editierbares Feld muss WM_CTLCOLOREDIT bearbeitet werden, ich glaube, das wurde im Verlauf des Threads schon erwähnt.

    Auch das klappt übrigens unter Win7 mit dem geposteten Testprogramm, wenn man es entsprechend ändert, nicht.

    Du hast nicht zufällig auch eine Idee, warum das unter Win7 anders läuft, als unter XP, bzw. wie man es unter Win7 so anpassen muss, damit es sich so verhält, wie unter XP?



  • Belli schrieb:

    Du hast nicht zufällig auch eine Idee, warum das unter Win7 anders läuft, als unter XP, bzw. wie man es unter Win7 so anpassen muss, damit es sich so verhält, wie unter XP?

    Bei mir läuft das Programm unter Win7 exakt genau so wie unter XP. Ich habe mit und ohne WS_DISABLED getestet.

    Hier die optimierte Version:

    case WM_CTLCOLOREDIT:     
         case WM_CTLCOLORSTATIC: 
             if((HWND)lParam == editFeld) {
                 HDC hdc = (HDC)wParam;
                 SetTextColor(hdc, RGB(0, 0, 0));
                 SetBkMode(hdc, TRANSPARENT);
                 if(brushNr) 
                    SetDCBrushColor(hdc, 0x00FF00); // select some color 
                 else  
                    SetDCBrushColor(hdc, 0x0000FF); // select some color
    
                 return (LPARAM)GetStockObject(DC_BRUSH); // return the DC brush
             }
             break;
    

    Einzige Änderung im Code ist die oben genannte Stelle, das Einbinden von tchar.h sowie die Umstellung aller Texte auf Unicode (Projektdefault bei VS).

    Wen die vielen Werbepopups nicht abschrecken - hier eine Version zum Testen.

    http://www21.zippyshare.com/v/55471876/file.html


Anmelden zum Antworten