2014-08-15 3 views
0

Во-первых, извините, если я чувствую себя высокомерным/грубым здесь.Раз и навсегда: как получить полностью прозрачный флажок, кнопку, переключатель и т. Д. В Windows API, а не с черным фоном?

Хорошо, так что все натолкнулись на это к настоящему времени (я надеюсь); Я просто не нашел любого адекватного ответа в любом месте. Мы начнем с общего управления 6 манифеста и

case WM_CTLCOLORSTATIC: 
    if (/* window has WS_EX_TRANSPARENT */) { 
     SetBkMode((HDC) wParam, TRANSPARENT); 
     return (LRESULT) GetStockObject(HOLLOW_BRUSH); 
    } 

и дать нашим этикетки WS_EX_TRANSPARENT. Они становятся прозрачными; Все идет нормально. Теперь мы должны добавить этот стиль к нашим флажкам (потому что по каким-то причинам флажки отвечают этому, а не WM_CTLCOLORBTN). И ... флажки становятся черными!

Есть ли способ сделать их полностью прозрачными, не прибегая к притяжению владельца? Я бы не стал сам рисовать флажки; Я бы предпочел не догадываться, выглядит ли это правильно или каковы размеры, если API-интерфейс API заканчивается на мне (и мне придется в будущем делать флажки, когда я добавляю собственные флажки в свои списки и я уже не доволен количеством угадываний).

Эти флажки нарисованы над элементом управления вкладкой. До сих пор я обнаружил пять диалоговых окон в Windows XP с прозрачными флажками на тематических вкладках: вкладка «Общие» свойств «Ярлык», вкладка «Панель задач» панели задач и «Свойства меню« Пуск », вкладка« Восстановление системы »« Свойства системы », вкладка« Общие »опций папки (переключатели) , и вкладку «Клавиатура» в разделе «Параметры специальных возможностей». Так что это, безусловно, должно быть возможно! Я уверен, что авторам пользовательских интерфейсов Windows не пришлось использовать пользовательскую ничью во всей ОС ... Что мы все не хватает?

Если мне нужно подкласс, это нормально (у меня уже есть подкласс в любом случае для обработки событий), но мне все же не нужно рисовать.

В качестве бонуса, как насчет кнопок? Переопределение WM_CTLCOLORBTN дает кнопкам черную рамку, но я замечаю, что ни один из стандартных диалогов, упомянутых выше, не пытается сделать углы кнопок прозрачными, поэтому eh:/

Спасибо!

+0

Стандартные элементы управления Win32 не поддерживает прозрачность сами по себе. Вы должны убить его. 'WS_EX_TRANSPARENT' - это не так. –

+0

Правильно, но здесь у меня создалось впечатление, что если я установлю 'WS_EX_TRANSPARENT', который сообщает диспетчеру окон не рисовать до тех пор, пока родительские окна не будут нарисованы, и верните полые кисти из сообщений' WM_CTLCOLORxxx', которые элементы управления будут рисовать с помощью полая кисть, которая ничего не рисует и, таким образом, показывает содержание ниже. Где это нарушение? – andlabs

+0

А я вижу, это на самом деле прозрачно для братьев и сестер, а не для родителя: | Поэтому я предполагаю, что флажки не обрабатывают 'WM_CTLCOLORSTATIC' должным образом, и в этом случае есть что-то еще, что я могу сделать, чтобы избежать необходимости рисовать фон самостоятельно? Я попробовал 'case WM_ERASEKGND: return 1;' в подклассе и вызывать 'SetBkMode()' там, оба без эффекта. – andlabs

ответ

0

В основном прибил это:

void paintControlBackground(HWND hwnd, HDC dc) 
{ 
    HWND parent; 
    RECT r; 
    POINT p; 
    int saved; 

    parent = GetParent(hwnd); 
    if (parent == NULL) 
     xpanic("error getting parent container of control in paintControlBackground()", GetLastError()); 
    if (GetWindowRect(hwnd, &r) == 0) 
     xpanic("error getting control's window rect in paintControlBackground()", GetLastError()); 
    // the above is a window rect; convert to client rect 
    p.x = r.left; 
    p.y = r.top; 
    if (ScreenToClient(parent, &p) == 0) 
     xpanic("error getting client origin of control in paintControlBackground()", GetLastError()); 
    saved = SaveDC(dc); 
    if (saved == 0) 
     xpanic("error saving DC info in paintControlBackground()", GetLastError()); 
    if (SetWindowOrgEx(dc, p.x, p.y, NULL) == 0) 
     xpanic("error moving window origin in paintControlBackground()", GetLastError()); 
    SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) dc, PRF_CLIENT); 
    if (RestoreDC(dc, saved) == 0) 
     xpanic("error restoring DC info in paintControlBackground()", GetLastError()); 
} 

    case WM_CTLCOLORSTATIC: 
    case WM_CTLCOLORBTN: 
     if (SetBkMode((HDC) wParam, TRANSPARENT) == 0) 
      xpanic("error setting transparent background mode to Labels", GetLastError()); 
     paintControlBackground((HWND) lParam, (HDC) wParam); 
     *lResult = (LRESULT) hollowBrush; 
     return TRUE; 

Есть несколько свободных концов:

Это не будет работать, если непосредственный родитель данного контроля является GroupBox; в этом случае вам нужно будет осмотреть class name и подойти к родительской цепочке.

Вам также необходимо реализовать WM_PRINTCLIENT на любых пользовательских контейнерах И в классе окна.

Это еще не работает для меток групповых ящиков; вы увидите текстуру, нарисованную должным образом, но линия групповой группы будет нарисована поверх нее. Я буду отмечать это как решение, когда я это выясню и обновляю этот пост этой информацией.

(Мерцание, которое я видел, похоже, вызвано сборщиком мусора, который используется другой частью программы, и, таким образом, пока не контролируется. Это, скорее всего, скоро изменится.)

Спасибо, тем временем!

0

Вы должны вернуть hbrBackground элемент зарегистрированного класса окна следующим образом:

case WM_CTLCOLORBTN: 
case WM_CTLCOLORSTATIC: { 
    wchar_t class_Name[100]; 
    GetClassName(hWnd, class_Name, 100); 
    WNDCLASS lpcls{}; 
    GetClassInfo(g_hInstance, class_Name, &lpcls); 

    return (LRESULT)lpcls.hbrBackground; 
} 
+0

Это действительно сработало! Благодарю. Я искал способ сделать Command Links прозрачным, он сработал. Этот ответ должен быть принят, это РАБОТАЕТ, и он НЕ требует слишком много строк кода. –