2009-05-15 3 views
2

Я реализовал панель инструментов панели задач DeskBand, используя BandObjectLib (Extending Explorer with Band Objects using .NET and Windows Forms) от Codeproject, модифицированный с поддержкой интерфейса IDeskBand2, который позволяет меню «Пуск» в Windows Vista сохранять прозрачность, когда включена панель инструментов панели задач DeskBand. Однако текст, отображаемый в поле со списком или текстовое поле, отображает цвет основного фона рабочего стола, смешанного с исходным цветом текста.Как заставить GDI + рендеринг ComboBox в C# на панели инструментов панели задач DeskBand? (проблема прозрачности)

Метка не имеет этой проблемы, поскольку ее обычно рисуют с использованием GDI (+), которая игнорирует DWMComposition на визуализированном тексте (а не на фоне метки).

я понял, что проблема в том, что путь DWM работает на Vista, в отношении некоторых элементов текста, который поясняется на следующих страницах:

Using Vista Controls on Aero Glass
Windows Vista Aero Pt. 1 - Adding Glass to a Windows Forms Application
Adding or Retrofitting Aero Glass into Legacy Windows Applications

Я использую только выпадающий на моя панель инструментов DeskBand, поэтому мне нужно было бы только знать, как заставить combobox не отображаться с использованием DWM, даже если DWM включен в системе и включен в DeskBand через реализацию интерфейса IDeskBand2.

Update: Я посмотрел в него дальше и коде C++ в Adding or Retrofitting Aero Glass into Legacy Windows Applications кажется наиболее вероятной ставкой на получение этой работы, так что текстовый дисплей выпадающего не является прозрачным. Если кто-то может посмотреть на этот код, относящийся только к combobox, и помочь мне заставить его работать на C# combobox, это сделает мой месяц! Я начал щедрость, чтобы надеяться получить ответ.

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

/* 
* 
* $RCSfile: aeroedit.cpp,v $ 
* $Source: /cvs/common/aeroedit.cpp,v $ 
* $Author: cvs $ 
* $Revision: 1.12 $ 
* $Date: 2007/05/20 10:38:25 $ 
* $State: Exp $ 
* Copyright (c) Stefan Kuhr 
*/ 

#include <windows.h> 
#include <tchar.h> 
#include "safassrt.h" 
#include "aaeroint.h" 
#include "aerosubc.h" 
#include "aeroglss.h" 
#include <windowsx.h> 
#include <gdiplus.h> 
using namespace Gdiplus; 

static void UpdateIfSelChanged(HWND hWnd, PAERO_SUBCLASS_WND_DATA pWndData) 
{ 
    DWORD dwFirst, dwLast; 
    SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwFirst, (LPARAM)&dwLast); 
    if(dwFirst!=pWndData->m_dwSelFirst || dwLast!=pWndData->m_dwSelLast) 
    { 
     pWndData->m_dwSelFirst = dwFirst; 
     pWndData->m_dwSelLast = dwLast; 
     VERIFY(InvalidateRect(hWnd, NULL, TRUE)); 
     VERIFY(UpdateWindow(hWnd)); 
    } 
} 


static LRESULT CALLBACK EditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    PAERO_SUBCLASS_WND_DATA pWndData = (PAERO_SUBCLASS_WND_DATA)GetProp(hWnd,   WINDOW_DATA_STRING); 
    ASSERT(pWndData); 
    ASSERT(pWndData->m_pDwmApiImpl); 
    WNDPROC pOldProc = pWndData->m_oldWndProc; 
    ASSERT(pOldProc); 
    PAERO_SUBCLASS_WND_DATA pWndDataParent =  (PAERO_SUBCLASS_WND_DATA)GetProp(GetParent(hWnd), WINDOW_DATA_STRING); 

    /// 
    /// if aero glass is turned off and if we are not in destruction code, 
    /// just call the original wnd proc we had prior to subclassing: 
    /// 
    if(WM_DESTROY!=uMsg && WM_NCDESTROY!=uMsg && WM_DWMCOMPOSITIONCHANGED!=uMsg &&  pWndDataParent && !pWndData->m_pDwmApiImpl->IsDwmCompositionEnabled()) 
     return CallWindowProc(pOldProc, hWnd, uMsg, wParam, lParam); 



    if(pWndData->m_uiRedrawMsg==uMsg && pWndData->m_dwFlags & WD_IN_PAINT_CONTROL) 
    { 
     HDC hdc = GetDC(hWnd); 
     hdc = GetDC(hWnd); 
     if(hdc) 
     { 
      RECT rcClient; 
      GetClientRect(hWnd, &rcClient); 

      BP_PAINTPARAMS params = { sizeof(BP_PAINTPARAMS) }; 
      params.dwFlags  = 0L;//BPPF_ERASE; 
      HDC hdcPaint = NULL; 
      HPAINTBUFFER hBufferedPaint = pWndData->m_pUxTheme->BeginBufferedPaint(hdc,  &rcClient, BPBF_TOPDOWNDIB, &params,  &hdcPaint); 
      if (hdcPaint) 
      { 
       LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); 
       DWORD_PTR dwSyscolorIdx = (dwStyle&WS_DISABLED ||   dwStyle&ES_READONLY)?COLOR_3DFACE:COLOR_WINDOW; 
       VERIFY(FillRect(hdcPaint, &rcClient, (HBRUSH)(dwSyscolorIdx+1))); 

       SendMessage(hWnd, WM_PRINTCLIENT, (WPARAM) hdcPaint,  PRF_CLIENT|PRF_CHECKVISIBLE); 

       /// Make every pixel opaque 
        VERIFY(S_OK==pWndData->m_pUxTheme->BufferedPaintMakeOpaque_(hBufferedPaint, &rcClient)); 
       VERIFY(S_OK==pWndData->m_pUxTheme->EndBufferedPaint(hBufferedPaint, TRUE));  
     } 

     VERIFY(1==ReleaseDC(hWnd, hdc)); 
     pWndData->m_dwFlags &= ~WD_IN_PAINT_CONTROL; 
    } 

    return 1; 
} 

switch(uMsg) 
{ 
    case WM_KEYDOWN: 
    {  
     LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); 
     if(dwStyle&WS_VSCROLL || dwStyle&ES_MULTILINE) 
     { 
      if(!(pWndData->m_dwFlags&WD_CARET_HIDDEN)) 
      { 
       HideCaret(hWnd); 
       pWndData->m_dwFlags|=WD_CARET_HIDDEN; 
      } 
     } 
    } 
     break; 
    case WM_KEYUP: 
    case WM_LBUTTONDOWN: 
    case WM_LBUTTONUP: 
    case WM_MOUSELEAVE: 
    { 
     LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); 
     if(dwStyle&WS_VSCROLL || dwStyle&ES_MULTILINE) 
     { 
      if(pWndData->m_dwFlags&WD_CARET_HIDDEN) 
      { 
       ShowCaret(hWnd); 
       pWndData->m_dwFlags&=~WD_CARET_HIDDEN; 
      } 

      UpdateIfSelChanged(hWnd, pWndData); 
     } 
    } 
     break; 
    case WM_NCPAINT: 
     { 
      LRESULT lRes = 0; 
      lRes = CallWindowProc(pOldProc, hWnd, uMsg, wParam, lParam); 
      DrawEditBorder(hWnd, pWndData); 
      return lRes; 
     } 
    case WM_NCDESTROY: 
    case WM_DESTROY: 
     VERIFY(UnsubclassControl(hWnd, EditProc, pWndData)); 
     break; 
} 

return CallWindowProc(pOldProc, hWnd, uMsg, wParam, lParam); 
} 

BOOL AeroSubClassEdit(HWND hwnd) 
{ 
    return AeroSubClassControl(hwnd, EditProc, WD_IN_PAINT_CONTROL); 
} 

Спасибо,

Джон Rennemeyer
MuvEnum, LLC

ответ

2

Это общая боль, я не знать, почему Microsoft не контролировала работу WinForms с DWMManager. TextBox легко сделать, вы можете перерисовать растровое изображение его над ним. DropDown сложнее, потому что в нем есть встроенный элемент управления «Редактировать». Поскольку это не элемент управления .Net (часть редактирования), вы не можете использовать классы .Net, чтобы легко перерисовать его (я все еще пытаюсь выяснить, как это сделать).

Я, однако, выяснил, как получить DropDown для рендеринга на стекле, но только если часть текстового поля отключена (что сделано путем изменения стиля). Не совсем идеально. Моя в VB.Net, и я все еще работаю над этим. Тем не менее, я был вдохновлен этим проектом, в котором этот парень вытащил его в C# и может быть большого подспорье для вас:

http://dwmwinform.codeplex.com/

В качестве примечания, WPF поддерживает эффект Aero Glass со всем его управлением , Это намного эффективнее, но также более трудоемко для использования (IMO ... и WPF не приносит вам пользы, если вы устанавливаете приложение WinForms в стиле ретро). Мне просто нравится WinForms с тех пор, как я пишу бизнес-приложения и на самом деле не забочусь или успеваю писать анимации (WPF классный, не правда ли, я предпочитаю WinForms).

Это мое начало, где я унаследовал ComboBox (In Vb.Net). Этот сайт не публикует весь класс правильно, поэтому я просто включу внутренности этого класса:

''' <summary> 
''' Enum of Windows messages that will trigger the redraw of the control 
''' </summary> 
''' <remarks></remarks> 
Public Enum WindowsMessage 
    WM_CHAR = &H100 
    WM_KEYDOWN = &H102 
    WM_MOUSEMOVE = &H200 
    WM_PAINT = 15 
    WM_PRINT = &H314 
End Enum 

''' <summary> 
''' Constructor 
''' </summary> 
''' <remarks></remarks> 
Sub New() 
    Me.DropDownStyle = ComboBoxStyle.DropDownList 
End Sub 

''' <summary> 
''' Processing of incoming messages. We're going to get a bitmap of the control and then 
''' redraw it onto the form when a few specified windows messages come through. 
''' </summary> 
''' <param name="m"></param>  
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 
    MyBase.WndProc(m) 

    Select Case m.Msg 
     Case WindowsMessage.WM_PAINT, WindowsMessage.WM_CHAR, WindowsMessage.WM_KEYDOWN, _ 
      WindowsMessage.WM_MOUSEMOVE, WindowsMessage.WM_PRINT 
      RedrawControlAsBitmap(Me.Handle) 
    End Select 

End Sub 

''' <summary> 
''' Redraws a given control as a bitmap ontop of itself. 
''' </summary> 
''' <param name="hwnd"></param> 
''' <remarks></remarks> 
Public Sub RedrawControlAsBitmap(ByVal hwnd As IntPtr) 

    Dim c As Control = Control.FromHandle(hwnd) 

    If c IsNot Nothing Then 
     Using bm As New Bitmap(c.Width, c.Height) 
      c.DrawToBitmap(bm, c.ClientRectangle) 

      Using g As Graphics = c.CreateGraphics 
       g.DrawImage(bm, New Point(0, 0)) 
      End Using 

     End Using 
    End If 

    c = Nothing 

End Sub 
Смежные вопросы