Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Внешний вид checkbox'a


Автор: rainbow86 25.12.2005, 13:46
Есть checkbox вот с такими стилями BS_AUTOCHECKBOX|WS_TABSTOP|BS_FLAT
Вроде бы всё нормально, но никак не удаётся поменять цвет рамки вокруг него.
Сейчас он черный, а мне нужен синий.
Нашел только FrameRect, для закрашивания области вокруг прямоугольника, но по моему там все проще.
Может кто подскажет как?
smile

Автор: Aleksandor 25.12.2005, 18:26
Ничего не приходит в голову кроме как рисовать кнопку самому smile
-1.
Рисуешь в Фотошопе 2 битмапа нужного размера и цвета - один для чекбокса без галочки и другой с галочкой или чем хочешь smile Сохраняешь в файлы checked.bmp и unchecked.bmp

0.
Определяешь в файле ресурсов 2 битмапа -
IDB_BITMAP1 BITMAP MOVEABLE PURE "Bitmaps\\checked.bmp"
IDB_BITMAP2 BITMAP MOVEABLE PURE "Bitmaps\\unchecked.bmp"

1.
в начале программы загружаешь битмапы
static HBITMAP hbmChecked = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1));
static HBITMAP hbmUncheked = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP2));
и создаешь кнопку

hwndButtonCheck = CreateWindow("BUTTON","", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
size_x-60, top_margin+47, 58, 37, hwndOutput, (HMENU) ID_BUTTON1, hInst, NULL);
...или просто добавляешь стиль BS_OWNERDRAW к кнопке если она в диалоге

2.
в оконной процедуре в ответ на сообщения WM_DRAWITEM рисуешь битмапы функцией StretchBlt

3.
очистка в конце программы
DeleteObject(hbmChecked);
DeleteObject(hbmUncheked);

Автор: rainbow86 25.12.2005, 21:00
Спасибо, счас попробую!

Автор: subzer0 24.8.2006, 20:29
А можно сделать так, чтобы состояние checked/unchecked от чекбоксов с BS_OWNERDRAW, можно было получать обычным способом?

Автор: Fixin 25.8.2006, 20:45
А как выглядит "необычный"?

Автор: subzer0 26.8.2006, 02:08
Обычный:

CheckDlgButton(hWnd,IDC_CHECKBOX1,BST_CHECKED);

IsDlgButtonChecked(hWnd,IDC_CHECKBOX1);

Автор: subzer0 26.8.2006, 05:32
Ладно, чёрт с ним с состоянием - проще в переменную записать.

Другая проблема: Написал ф-ию для смены внешнего вида чекбоксов. Но работает как-то через раз. Картинка меняется только со второго раза. Например если два чекбокса и я нажал на первый, то когда я жму на второй меняется картинка на первом, а потом уже при повторном нажатии - на втором.
Код

void RedrawCtl (int ctl, HBITMAP destImage)
{
    HWND hCtlWnd = GetDlgItem(hDlg,ctl);
    HDC hdc,hmdc;
    BITMAP bm;

    hdc = GetWindowDC(hCtlWnd);
    hmdc = CreateCompatibleDC(hdc);
    
    SelectObject(hmdc,destImage);
    GetObject(destImage,sizeof(bm),(LPSTR)&bm);

    BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hmdc,0,0,SRCCOPY);
    
    DeleteDC(hmdc);
    ReleaseDC(hCtlWnd,hdc);
}
Подскажите где я ошибся? smile 

Автор: GremlinProg 26.8.2006, 10:15
Ошибся в самом подходе прорисовки. Напрямую перерисовывать контрол бессмысленно, установи ownerdraw флаг и перехватывай WM_DRAWITEM у диалога. Так ты получишь возможность обновить контрол в момент изменения состояния чекбокса.

Добавлено @ 10:19 
Вот, кстати, Aleksandor, о WM_DRAWITEM уже упоминал

Автор: subzer0 26.8.2006, 17:27
Именно так я и пытался делать. Но проблема в том, что когда я пишу свой RedrawCtl() внутри WM_DRAWITEM он косячит. А если прописать эту ф-ию по WM_COMMAND (клик на чекбоксе), то всё работает нормально.

Автор: GremlinProg 26.8.2006, 17:54
Тогда непонятно следующее:
Код

hdc = GetWindowDC(hCtlWnd);
...
ReleaseDC(hCtlWnd,hdc);

Зачем открывать девайс?
WM_DRAWITEM уже передает корректный девайс. В твоем случае, RedrawCtl нужно передать hdc в списке параметров, а не открывать его внутри функции.
Покажи обработку WM_DRAWITEM.

Автор: subzer0 27.8.2006, 01:46
Код

case WM_DRAWITEM:
RedrawCtl(IDC_CHECK1,stateCheck1?hbmpChecked:hbmpUnchecked);
RedrawCtl(IDC_CHECK2,stateCheck2?hbmpChecked:hbmpUnchecked);
break;

Автор: GremlinProg 27.8.2006, 09:36
Вот об этом я как раз и говорил. Используй члены структуры DRAWITEMSTRUCT:
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/comboboxes/comboboxreference/comboboxstructures/drawitemstruct.asp
для сообщения WM_DRAWITEM:
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/comboboxes/comboboxreference/comboboxmessages/wm_drawitem.asp

Добавлено @ 09:44 
прототип должен выглядеть так:
Код

void RedrawCtl (int ctl, HBITMAP destImage,HDC hdc);

а WM_DRAWITEM так:
Код

DRAWITEMSTRUCT&ds    = *(DRAWITEMSTRUCT*)lParam;
switch(ds.CtlID){
    case IDC_CHECK1:
        RedrawCtl(IDC_CHECK1,(ds.itemState&ODS_CHECKED?hbmpChecked:hbmpUnchecked),ds.hDC);
        break;
    case IDC_CHECK2:
        RedrawCtl(IDC_CHECK2,(ds.itemState&ODS_CHECKED?hbmpChecked:hbmpUnchecked),ds.hDC);
        break;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)