2009-05-15 5 views
2

J'ai implémenté une barre d'outils DeskBand à l'aide de BandObjectLib (Extending Explorer with Band Objects using .NET and Windows Forms) de Codeproject, modifiée avec la prise en charge de l'interface IDeskBand2 qui permet au menu Démarrer de Windows Vista de conserver la transparence lorsque ma barre d'outils DeskBand est activée. Cependant, le texte affiché dans une zone de liste déroulante ou une zone de texte affiche la couleur de l'arrière-plan du bureau sous-jacent fusionné avec la couleur d'origine du texte.Comment forcer le rendu GDI + d'une zone de liste déroulante en C# sur une barre d'outils de barre des tâches DeskBand? (problème de transparence)

Une étiquette n'a pas ce problème car elle est normalement dessinée en utilisant GDI (+) qui ignore DWMComposition sur le texte rendu (pas l'arrière-plan de l'étiquette).

Je figurés le problème est que la façon dont DWM fonctionne sur Vista concernant certains éléments de texte qui est expliqué dans les pages suivantes:

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

Je n'utilise un combobox sur ma barre d'outils DeskBand donc je ne devrais savoir comment forcer la liste déroulante à ne pas afficher en utilisant DWM même si DWM est activé sur le système et est activé sur le DeskBand grâce à l'implémentation de l'interface IDeskBand2.

Mise à jour: J'ai examiné plus avant et le code C++ à Adding or Retrofitting Aero Glass into Legacy Windows Applications semble le pari le plus probable sur l'obtention de ce travail que le texte d'affichage combobox n'est pas transparent. Si quelqu'un peut regarder ce code se rapportant uniquement à la liste déroulante et m'aider à le faire fonctionner pour un combobox C#, cela ferait mon mois! J'ai commencé une prime pour espérer obtenir une réponse. Ci-dessous, la classe EditProc.cpp du projet mentionné ci-dessus qui devrait fournir un aperçu rapide de ce que je considère comme une solution. Pour obtenir une image complète, vous aurez besoin de regarder l'ensemble du projet:

/* 
* 
* $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); 
} 

Merci,

John Rennemeyer
MuvEnum, LLC

Répondre

2

Ceci est une douleur totale, je ne savoir pourquoi Microsoft n'a pas les contrôles WinForms fonctionnent avec le DWMManager. Le TextBox est facile à faire, vous pouvez repeindre une image bitmap de celui-ci. DropDown est plus compliqué car il contient une zone de contrôle natif 'Edit'. Comme ce n'est pas un contrôle .Net (le morceau d'édition) alors vous ne pouvez pas utiliser les classes .Net pour le redessiner facilement (j'essaie toujours de comprendre comment faire cela).

J'ai cependant trouvé comment obtenir un DropDown pour le rendu sur le verre mais seulement si la partie textbox est désactivée (ce qui est fait en changeant le style). Pas exactement idéal. Le mien est dans VB.Net et je travaille toujours dessus. Cependant, je me suis inspiré de ce projet où ce gars-là a réussi à le faire en C# et peut être d'une grande aide pour vous:

http://dwmwinform.codeplex.com/

Comme une note de côté, WPF supporte l'effet Aero Glass avec toutes ses commandes . C'est beaucoup plus puissant mais aussi beaucoup plus long à utiliser (IMO ... et, WPF ne vous convient pas si vous ajustez une application WinForms). J'ai tendance à aimer WinForms depuis que j'écris des applications d'affaires et que je n'ai pas vraiment le temps d'écrire des animations (WPF est cool, ne me trompe pas, je préfère WinForms).

C'est mon début où j'ai hérité d'un ComboBox (In Vb.Net). Ce site ne publie pas toute la classe correctement donc je vais juste inclure l'intérieur de la classe:

''' <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 
Questions connexes