3

Codeproject の BandObjectLib (Extended Explorer with Band Objects using .NET and Windows Forms ) を使用して DeskBand タスクバー ツールバーを実装し、IDeskBand2 インターフェイスをサポートするように変更しました。これにより、Windows Vista の [スタート] メニューで DeskBand タスクバー ツールバーが透明性を維持できるようになります。有効になっています。ただし、コンボボックスまたはテキストボックスに表示されるテキストは、元のテキストの色とブレンドされた下にあるデスクトップの背景の色を表示します。

ラベルは通常、レンダリングされたテキスト (ラベルの背景ではない) の DWMComposition を無視する GDI(+) を使用して描画されるため、この問題はありません。

問題は、次のページで説明されている特定のテキスト要素に関して、DWM が Vista で動作するためだと考えました。

Aero Glass で Vista コントロールを使用する
Windows Vista Aero Pt. 1 - Windows フォーム アプリケーションへの Glass の
追加 レガシー Windows アプリケーションへの Aero Glass の追加またはレトロフィット

私は DeskBand ツールバーでコンボボックスのみを使用しているため、システムで DWM が有効になっていて、IDeskBand2 インターフェイスの実装を通じて DeskBand で有効になっている場合でも、DWM を使用してコンボボックスを強制的に表示しないようにする方法を知る必要があるだけです。

更新:さらに調べたところ、「Aero Glass をレガシー Windows アプリケーションに追加またはレトロフィットする」の C++ コードが、これを機能させるための最も可能性の高い賭けのように思われるため、コンボボックスの表示テキストは透明ではありません。誰かがコンボボックスに関連するそのコードを見て、C# コンボボックスで動作させるのを手伝ってくれるなら、それは私の月になるでしょう! うまくいけば答えを得るための賞金を開始しました。

以下は、上記のプロジェクトの 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);
}

ありがとうございました、

John Rennemeyer
MuvEnum、LLC

4

1 に答える 1

2

これはまったくの苦痛です。Microsoft が WinForms コントロールを DWMManager で動作させなかった理由がわかりません。TextBox は簡単に実行できます。その上にビットマップを再描画できます。ドロップダウンは、内部にネイティブ コントロールの [編集] ボックスがあるため、より複雑です。これは .Net コントロール (編集部分) ではないため、.Net クラスを使用して簡単に再描画することはできません (これを行う方法をまだ見つけようとしています)。

ただし、ドロップダウンをガラスにレンダリングする方法を理解しましたが、テキストボックス部分が無効になっている場合に限ります(スタイルを変更することによって行われます)。正確には理想的ではありません。私のはVB.Netにあり、まだ取り組んでいます。しかし、私はこの男が C# でそれをやってのけたこのプロジェクトに触発されました。

http://dwmwinform.codeplex.com/

補足として、WPF はすべてのコントロールで Aero Glass 効果をサポートしています。それははるかに強力ですが、使用するのに時間がかかります(IMO ...そして、WinFormsアプリをレトロフィッティングしている場合、WPFは何の役にも立ちません)。私はビジネスアプリケーションを書いていて、アニメーションを書くことをあまり気にしていないか、書く時間がないので、WinForms が好きな傾向があります (WPF はクールです。間違ってはいけません。私は WinForms の方が好きです)。

これは、ComboBox (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
于 2009-05-30T17:38:46.317 に答える