Изменить цвет кнопок

Тема в разделе "WASM.BEGINNERS", создана пользователем Sturgeon, 13 ноя 2006.

  1. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Здравствуйте все!
    Снова я, снова с ламерским вопросом.
    Пытаюсь изменить цвет окна и всех контролов со стандартного серого на что-нибудь приятное зелененькое.
    Цвет главного окна изменил, поместив в соответствующее поле нужное значение.
    Код (Text):
    1. RGB    114,255,128
    2. PUSH EAX
    3. CALL CreateSolidBrush
    4. mov wc.hbrBackground,  EAX
    При этом цвет окна изменился, а кнопки, надписи, меню остались серенькими. В принципе логично,- подумал я. Ведь свойства окна и кнопок задаются в разных местах?
    Ладно, пробую изменить цвет кнопок с помощью функции SetBkColor.

    В структуру сообщения WM_PAINT (после вызова BeginPaint) включаю:
    Код (Text):
    1. invoke SetBkColor, Button1, 3  ; где  Button1 хендл кнопки
    И... никаких изменений:dntknw:
    Пробовал вызывать SetBkColor, непосредственно после создания кнопки:

    Код (Text):
    1. invoke CreateWindowEx, WS_EX_LEFT,
    2.         ADDR szBtnClass,
    3.         ADDR szBtn1Text,
    4.         WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,
    5.         Button1L, Button1T, Button1W, Button1H,
    6.     hWnd, NULL, hInst, NULL
    7.     mov   Button1, eax
    8. invoke SetBkColor, Button1, 255
    Тот же результат. В смысле отсутствие результата.

    Пробовал изменять фон кнопки с помощью посылки сообщения:

    INVOKE SendMessage, Button1, TVM_SETBKCOLOR, 0, 00000000h

    И, блин, опять ничего...
    Подскажите пожалуйста, где я опять косячу?
     
  2. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    WM_CTLCOLORBTN
    WM_CTLCOLOREDIT
    WM_CTLCOLORDLG
    WM_CTLCOLORLISTBOX
    WM_CTLCOLORSCROLLBAR
    WM_CTLCOLORSTATIC

    ищи описание.
     
  3. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Вроде почитал на MSDN, но мало что прояснилось. Так. Сообщение WM_CTLCOLORBTN посылается родительскому окну кнопки для того, чтобы изменять фон и содержимое кнопки. Посылать сообщение необходимо перед тем как нарисовать кнопку.

    Посылка собщения должна выглядеть таким образом (как я понял):
    invoke SendMessage, hWnd, WM_CTLCOLORBTN, 45, Button1
    Непонятно, если кнопка еще не нарисована, то как мы узнаем ее хендл? Попробовал, конечно, поставить перед CreateWindowEx (для кнопки). Ничего не получилось.
    Если под рисованием имеется ввиду ShowWindow, то я на всякий случай пробовал посылать сообщение и перед ее вызовом. Результата нет.

    Если я правильно понял,то в wParam сообщения помещается указатель на будущее содержимое кнопки "Handle to the display context for the button". А что это должно быть если мне надо только поменять цвет?

    Если кто-нибудь знает ссылку на такой пример, дайте пожалуйста.
     
  4. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Ты направильно понял.
    WM_CTLCOLORBTN - это нотификация, и отсылается родительскому(по отношению к кнопке) окну. При обработке, WndProc должна вернуть хенд кисти. Ксить создавай через CreateSolidBrush.
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Это сообщение грубо говоря отсылается системой, и ты его должен обработать в своём главном окне.
     
  6. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
  7. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    То есть все должно выглядеть вот так?

    .ELSEIF uMsg == WM_CTLCOLORBTN
    mov eax, lParam
    .if eax == Button1
    RGB 122,122,1
    INVOKE CreateSolidBrush, EAX
    INVOKE SetBkColor,Button1,EAX
    .endif

    Опять ничего не вышло:dntknw:
     
  8. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Код (Text):
    1. ...
    2.  
    3. .data
    4. hbrBtnBrush dd  0
    5.  
    6. ...
    7.  
    8. ; При инициализации
    9.     RGB 122,122,1
    10.     push eax
    11.     call CreateSolidBrush
    12.     mov hbrBtnBrush, eax
    13. ...
    14.  
    15. ; Функция окна
    16.  
    17. ...
    18.  
    19.     .ELSEIF uMsg == WM_CTLCOLORBTN
    20.         mov eax, lParam
    21.         .if eax == Button1
    22.    
    23.         ; Устанавливаем прозрачный фон для текста кнопки
    24.             push TRANSPARENT
    25.             push wParam
    26.             call SetBkMode
    27.    
    28.         ; Устанавливаем цвет текста кнопки
    29.             RGB 0,0,128
    30.             push eax
    31.             push wParam
    32.             call SetTextColor
    33.            
    34.         ; Возвращаемым значением функции окна должен быть хендл кисти
    35.             mov eax, hbrBtnBrush
    36.            
    37.         ; От этой инструкции до выхода из функции eax не должен изменится
    38.     .endif
    39. ...
     
  9. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Огромное спасибо, rmn!!!
    Как все-таки сложно все это усваивать. Вроде и читаю много, и в разных исходниках ковыряюсь, и в отладчике гоняю все что можно, А все равно очень туго идет:dntknw:
    Спасибо еще раз!
     
  10. Zhelezovsky

    Zhelezovsky Member

    Публикаций:
    0
    Регистрация:
    24 окт 2006
    Сообщения:
    39
    Попробовал похожим образом:
    Код (Text):
    1. .IF uMsg==WM_CREATE
    2. ...
    3. RGB 122,122,1
    4. invoke CreateSolidBrush, eax
    5. mov hbrBtnBrush, eax
    6. ...
    7. .ELSEIF uMsg == WM_CTLCOLORBTN
    8. mov eax, lParam
    9. .IF eax==hbExit
    10. invoke SetBkMode, wParam, TRANSPARENT
    11. RGB 0,0,128
    12. invoke SetTextColor, wParam, eax
    13. mov eax, hbrBtnBrush
    14. ret
    15. .ENDIF
    У меня не заработало. Кнопка как была стандартного цвета с чёрным шрифтом, так и осталась.
    Какие ещё тут нюансы могут быть?
     
  11. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    У меня, кстати, тоже почемуто не получилось:dntknw:. Все хотел отписаться, но, то времени не было, то я все пытался сам чего-то поправить.
    Ньюансы кое-какие есть. Из MSDN:
    Buttons with the BS_PUSHBUTTON, BS_DEFPUSHBUTTON, or BS_PUSHLIKE styles do not use the returned brush. Buttons with these styles are always drawn with the default system colors.
    Пробовал без этих стилей, но все равно не получается.
     
  12. Jupiter

    Jupiter Jupiter

    Публикаций:
    0
    Регистрация:
    12 авг 2004
    Сообщения:
    532
    Адрес:
    Russia
    который раз отвечаю на данный вопрос:
    см. исходники XXControls, конкретно XXButton
     
  13. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Поковырялся с XXControls и еще с парой исходников. Оказалось для диалоговых окошек. И вообще довольно перегружено информацией. Очень тяжело воспринимается. Ничего не понял:dntknw:
     
  14. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Простите, что поднимаю старую тему, но вопрос еще остаетя актуальным для меня. За это время прочесал множество ресурсов (как русских, так и иностранных) и сложилась интересная ситуация. На всех форумах, где я задавал этот вопрос, развитие событий было примерно одинаковым. Либо давали пример кода, аналогичного тому, что привел rmn; либо отсылали к MSDN; либо давали ссылку на какой-нибудь левый исходник мало связаный с вопросом. Я честно пытался все это применять, но результата так и не добился. После этого я обычно признавался в собственной чайниковости стыдливо просил помочь исправить мой исходник. После этого все куда-то отваливали.:dntknw: На англоязычных форумах куча тем с вопросом "How use WM_CTLCOLORBTN", но все они по содержанию аналогичны текущему топику.
    Проблему я смог решить несколькими путями. Использовать в качестве кнопок картинки, сабклассинг или рисование кнопок вручную. Но это какие-то кривые обходные пути. А вопрос так и остался. Как с помощью обработки WM_CTLCOLORBTN изменить цвет кнопки? Что интересно со "статиком" и "эдитом" все получается, а кнопки как заколдованные:dntknw:.
    Если кто-нибудь делал такие вещи, не посчитайте за труд, выложите, пожалуйста, простенький рабочий исходник.
     
  15. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Эти стили как раз и задают обычную кнопку.
     
  16. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    MSDN:
    The WM_CTLCOLORBTN message is sent to the parent window of a button before drawing the button. The parent window can change the button's text and background colors. However, only owner-drawn buttons respond to the parent window processing this message.
     
  17. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Sturgeon
    Только так.

    ЗЫ: Во всяком случае я именно так обычно делаю (3й вариант или через owner-drawn) и никаких неудобств не испытываю.

    ЗЫЫ: Вот пример нашёл у себя на C (это не owner-drawn, а самодельный контрол, прикидывающийся кнопкой):
    Код (Text):
    1. long __stdcall ButtonProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
    2. char button_buf[32];
    3. HDC hDC;
    4. PAINTSTRUCT paint;
    5. HPEN hOldPen;
    6. HBRUSH hOldBrush;
    7. HFONT hOldFont;
    8. RECT rc;
    9. POINT pt;
    10. int h, i, j;
    11.    switch(uMsg){
    12.       case WM_ERASEBKGND: return 1;
    13.       case WM_PAINT:
    14.          hDC = BeginPaint(hWnd,&paint);
    15.          if(paint.rcPaint.bottom != paint.rcPaint.top){
    16.             GetClientRect(hWnd,&rc);
    17.             GetWindowText(hWnd,button_buf,sizeof(button_buf) - 1);
    18.             i = IsWindowEnabled(hWnd);
    19.             j = GetWindowLong(hWnd,GWL_USERDATA);
    20.             h = j & 2;
    21.             j &= 1;
    22.             SetBkMode(hDC,TRANSPARENT);
    23.             hOldFont = SelectObject(hDC,hStaticFnt);
    24.             hOldPen = SelectObject(hDC,CreatePen(PS_SOLID,0,h ? 0xFFFFFF : (j ? 0x6A240A : 0x808080)));
    25.             SetTextColor(hDC,h ? 0xFFFFFF : (i ? 0 : 0x808080));
    26.             hOldBrush = SelectObject(hDC,CreateSolidBrush(h ? 0x800000 : (j ? 0xE2D2CB : 0xCFD6DA)));
    27.             Rectangle(hDC,0,0,rc.right,rc.bottom);
    28.             DrawTextEx(hDC,button_buf,-1,&rc,DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE,0);
    29.             DeleteObject(SelectObject(hDC,hOldPen));
    30.             DeleteObject(SelectObject(hDC,hOldBrush));
    31.             SelectObject(hDC,hOldFont);
    32.          }
    33.          EndPaint(hWnd,&paint);
    34.          break;
    35.       case WM_LBUTTONDOWN:
    36.          SetWindowLong(hWnd,GWL_USERDATA,2);
    37.          InvalidateRect(hWnd,0,0);
    38.          break;
    39.       case WM_LBUTTONUP:
    40.          SetWindowLong(hWnd,GWL_USERDATA,1);
    41.          InvalidateRect(hWnd,0,0);
    42.          PostMessage(GetParent(hWnd),WM_COMMAND,GetWindowLong(hWnd,GWL_ID),0);
    43.          break;
    44.       case WM_MOUSEMOVE:
    45.          pt.x = LOWORD(lParam);
    46.          pt.y = HIWORD(lParam);
    47.          GetClientRect(hWnd,&rc);
    48.          if(!PtInRect(&rc,pt)){
    49.             ReleaseCapture();
    50.             SetWindowLong(hWnd,GWL_USERDATA,0);
    51.           }else{
    52.             if(GetCapture() != hWnd){
    53.                SetCapture(hWnd);
    54.                SetWindowLong(hWnd,GWL_USERDATA,1);
    55.             }else break;
    56.          }
    57.        case WM_ENABLE:
    58.          InvalidateRect(hWnd,0,0);
    59.          break;
    60.       default: return DefWindowProc(hWnd,uMsg,wParam,lParam);
    61.    }
    62.    return 0;
    63. }
    Регистрируется обычным способом... Далее можно использовать хоть в шаблоне диалога вместо обычных кнопок, хоть по CreateWindow.
     
  18. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Quantum
    То есть WM_CTLCOLORBTN использовать нельзя? А для чего он тогда вообще нужен?

    rmn
    n0name
    Есть у меня MSDN. И с BS_OWNERDRAW я тоже пробовал. Можете написать рабочий код?
     
  19. Jupiter

    Jupiter Jupiter

    Публикаций:
    0
    Регистрация:
    12 авг 2004
    Сообщения:
    532
    Адрес:
    Russia
    что именно тебе не понятно в исходнике XXControls?
     
  20. Sturgeon

    Sturgeon New Member

    Публикаций:
    0
    Регистрация:
    17 окт 2006
    Сообщения:
    111
    Jupiter
    Это для диалогового окна, а хотелось для обычного.
    И еще я пробовал перетранслировать его со своими настройками RGB, но постоянно требовались дллки, библиотеки, инклуды. В итоге я запутался и ничего у меня не получилось.
    З.Ы. Это не потому, что исходник непонятный, а потому, что я пока чайник.