0

紹介と関連情報:

グラデーションの背景を持つ静的コントロールを作成したいと考えています。

私はそれを次のようにしたい:

メイン ウィンドウの背景にグラデーションを作成し、その背景の上に透明な静的コントロールを配置します。

そのために、静的コントロールがあるべき位置にグラデーションを配置するRECT変数をハンドラーに作成しました。WM_PAINT

また、ちらつきを避けるためにダブルバッファリングを使用しようとしています(WM_ERASEBKGNDフラグCS_VREDRAWを処理し、CS_HREDRAWウィンドウクラスから削除しました)。

WM_SIZEウィンドウを無効にし、静的コントロールを適切に再配置するメッセージも処理しました。

私のWM_CTLCOLORSTATICハンドラーでは、 が返されNULL_BRUSHました。

Visual Studio のアプリケーション ウィザードを使用して、これを説明するデモ アプリケーションを作成しました。

純粋な Win32 API と C++ を使用して、Windows XP で作業しています。

WM_PAINT以下に、上記の他のハンドラーの 、およびスニペットの変更されたコードを送信します。

    case WM_CREATE:
         {
             // get rectangle dimensions of the main window

             RECT rec;
             GetClientRect( hWnd, &rec );

             /******* main window's static control ******/

             HWND StaticControl = CreateWindowEx( 0, L"Static", L"", 
                                     WS_VISIBLE | WS_CHILD | SS_NOTIFY,
                                     ( 3 * ( rec.right - rec.left ) / 4 - 340 ) / 3,
                                     120 + ( rec.bottom - rec.top - 450 ) / 3, 
                                     150, 150, hWnd, (HMENU)4000, hInst, 0);
         }
         return (LRESULT)0;

    case WM_SIZE:
        {
             RECT rec; // main window's client rectangle

             GetClientRect( hWnd, &rec ); 

             SetWindowPos( GetDlgItem( hWnd, 4000 ),
                           NULL,
                           ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
                           120 + ( rec.bottom - rec.top - 450 ) / 3, 150, 150,
                           SWP_NOZORDER );

            InvalidateRect( hWnd, NULL, FALSE); 
        }
        return (LRESULT)0;

    case WM_ERASEBKGND:
        return (LRESULT)1;

    case WM_CTLCOLORSTATIC:
        return (LRESULT)( (HBRUSH)GetStockObject(NULL_BRUSH) );

    case WM_PAINT:
        {
            hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code here...

            RECT r; // rectangle for main window's client area

            GetClientRect( hWnd, &r);

            HDC MemDC = CreateCompatibleDC(hdc); // back buffer

            // compatible bitmap for MemDC

            HBITMAP bmp = CreateCompatibleBitmap( hdc,
                                                  r.right - r.left, 
                                                  r.bottom - r.top ),
                    oldBmp = (HBITMAP)SelectObject( MemDC, bmp ); // needed for cleanup

            /***** draw a reference header at the top of the window *******/

            // position it properly at the top

            RECT rect;

            rect.left = r.left;
            rect.top = r.top;
            rect.right = r.right;
            rect.bottom = 120;

            FillRect( MemDC, &rect, (HBRUSH)GetStockObject(LTGRAY_BRUSH) );

            /**** main window's gradient background *******/

            //============ down triangle =========//

            TRIVERTEX vertex[3];

            vertex[0].x     = r.right;
            vertex[0].y     = r.bottom - r.top;
            vertex[0].Red   = 0xDB00;
            vertex[0].Green = 0xE500;
            vertex[0].Blue  = 0xF100;
            vertex[0].Alpha = 0x0000;

            vertex[1].x     = r.left;
            vertex[1].y     = r.bottom - r.top;
            vertex[1].Red   = 0x9500;
            vertex[1].Green = 0xB300;
            vertex[1].Blue  = 0xD700;
            vertex[1].Alpha = 0x0000;

            vertex[2].x     = r.left;
            vertex[2].y     = r.top + 120; 
            vertex[2].Red   = 0xDB00;
            vertex[2].Green = 0xE500;
            vertex[2].Blue  = 0xF100;
            vertex[2].Alpha = 0x0000;

            // Create a GRADIENT_TRIANGLE structure that
            // references the TRIVERTEX vertices.

            GRADIENT_TRIANGLE gTriangle;

            gTriangle.Vertex1 = 0;
            gTriangle.Vertex2 = 1;
            gTriangle.Vertex3 = 2;

            // Draw a shaded triangle.

            GradientFill( MemDC, vertex, 3, &gTriangle, 1, GRADIENT_FILL_TRIANGLE);

            //=============== upper triangle =================//

            TRIVERTEX vertex1[3];

            vertex1[0].x     = r.right;
            vertex1[0].y     = r.bottom - r.top;
            vertex1[0].Red   = 0xDB00;
            vertex1[0].Green = 0xE500;
            vertex1[0].Blue  = 0xF100;
            vertex1[0].Alpha = 0x0000;

            vertex1[1].x     = r.right;
            vertex1[1].y     = r.top + 120;
            vertex1[1].Red   = 0x9500;
            vertex1[1].Green = 0xB300;
            vertex1[1].Blue  = 0xD700;
            vertex1[1].Alpha = 0x0000;

            vertex1[2].x     = r.left;
            vertex1[2].y     = r.top + 120; 
            vertex1[2].Red   = 0xDB00;
            vertex1[2].Green = 0xE500;
            vertex1[2].Blue  = 0xF100;
            vertex1[2].Alpha = 0x0000;

            // Draw a shaded triangle.

            GradientFill( MemDC, vertex1, 3, &gTriangle, 1, GRADIENT_FILL_TRIANGLE);

            //**** draw background of the static control ****//

            //position it properly 

            rect.left = ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
            rect.top = 120 + ( r.bottom - r.top - 450 ) / 3;
            rect.right = 150 + ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
            rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3; // this one fails!!!

            //FillRect( MemDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH) );

            // vertexes for static's gradient color

            //================= top rectangle =====================//

            TRIVERTEX vertexS[2], vertex1S[2] ;

            vertexS[0].x     = rect.left;
            vertexS[0].y     = rect.top;
            vertexS[0].Red   = 0x9500;
            vertexS[0].Green = 0xB300;
            vertexS[0].Blue  = 0xD700;
            vertexS[0].Alpha = 0x0000;

            vertexS[1].x     = rect.right;
            vertexS[1].y     = ( rect.bottom - rect.top ) / 2; 
            vertexS[1].Red   = 0x4F00;
            vertexS[1].Green = 0x8B00;
            vertexS[1].Blue  = 0xBD00;
            vertexS[1].Alpha = 0x0000;

            //================== bottom rectangle ====================//

            vertex1S[0].x     = rect.left;
            vertex1S[0].y     = ( rect.bottom - rect.top ) / 2; 
            vertex1S[0].Red   = 0x4F00;
            vertex1S[0].Green = 0x8B00;
            vertex1S[0].Blue  = 0xBD00;
            vertex1S[0].Alpha = 0x0000;

            vertex1S[1].x     = rect.right;
            vertex1S[1].y     = rect.bottom;
            vertex1S[1].Red   = 0x9500;
            vertex1S[1].Green = 0xB300;
            vertex1S[1].Blue  = 0xD700;
            vertex1S[1].Alpha = 0x0000;

            // Create a GRADIENT_RECT structure that 
            // references the TRIVERTEX vertices.

            GRADIENT_RECT gRect;

            gRect.UpperLeft  = 0;
            gRect.LowerRight = 1;

            // Draw a shaded rectangle. 

            GradientFill( MemDC, vertexS, 2, &gRect, 1, GRADIENT_FILL_RECT_V );
            GradientFill( MemDC, vertex1S, 2, &gRect, 1, GRADIENT_FILL_RECT_V );

            /****** draw back buffer on the screen DC *****************/

            BitBlt( hdc, 0, 0, r.right - r.left, r.bottom - r.top,
                    MemDC, 0, 0, SRCCOPY );

            /************** cleanup *******************/

            SelectObject( MemDC, oldBmp );

            DeleteObject(bmp); // compatible bitmap for MemDC

            DeleteDC(MemDC);

            EndPaint(hWnd, &ps);
        }
        return (LRESULT)0;

問題:

GradientFillハンドラーでAPIを使用するWM_PAINTと、本来よりも大きな長方形が画面に表示されます。

以下の図は、この結果を示しています。

ここに画像の説明を入力

同じ長方形をソリッド ブラシで塗りつぶそうとすると、すべて正常に動作します。

以下の図は、この結果を示しています。

ここに画像の説明を入力

問題を解決するための私の努力:

長方形の座標が設定されている場所にブレークポイントを配置しましたが、問題はありませんでした。

また、 をGradientFill返すTRUEので失敗しません。

質問:

これを修正する方法は?

前もって感謝します。

よろしく。

4

1 に答える 1

1

頂点の計算が間違っているだけだと思います:

        vertexS[1].y     = ( rect.bottom - rect.top ) / 2; 
        /* .... */
        vertex1S[0].y     = ( rect.bottom - rect.top ) / 2;

rect.top + ( rect.bottom - rect.top ) / 2それらは、または同様のものであるべきですか?それとも単にrect.bottomそれぞれrect.top

何を達成しようとしているのかにもよりますが、いずれにせよ、現時点ではあなたが望んでいるものではないと思います。コメントアウトしたものと同じ形状を使用rect.bottomして取得する必要があります。rect.topFillRect

于 2013-11-11T04:26:20.697 に答える