Shade the selection area

Feature Requests for GdPicture.NET.
Post Reply
User avatar
justcode
Posts: 26
Joined: Wed Jul 15, 2009 9:20 pm

Shade the selection area

Post by justcode » Tue Dec 08, 2009 7:21 pm

It would be nice if you could select a color to shade the selected rect area in the viewer. Then when the user selects an area on the screen, the selected portion is more pronounced.

I currently place text over a form overlay and allow the user to search the text. When found, I select the text using the selection rectangle. The user has a hard time to see the selection area on the screen, especially if it is just a few characters.

I tried to use the PaintControl message to shade the selected area using AlphaBlend. This works fine until a window is moved in front of the view, because I do not know the invalidated area on the HDC the code just darkens the selection rectangle to a solid color. It would be nice if the PaintControl was passed the invalidated area of the image that was just drawn in the viewer.

below is a screen scrape to show what I mean by a shaded selection rect.
screenscrape.png
Selected area shaded blue at 15% transparency

User avatar
justcode
Posts: 26
Joined: Wed Jul 15, 2009 9:20 pm

Re: Shade the selection area

Post by justcode » Thu Jan 14, 2010 6:10 pm

I did find a way to accomplish this using the current available calls. You have to create a CWND wrapper class for the viewer control and override the OnPaint method used by the window. The following code seems to work and it is what I am currently using. It would be nice if it was implemented in the class directly. I am using MFC, but this can easily be re-written for Win32 API. I use a generic CMemDC class which is easily found on Google.

Code: Select all

void CGDViewerCtrl::OnPaint() 
{
    // device context for painting
    CPaintDC screenDC(this); 

    // get the current clipping area
    CRect rClipBox;
    int iValue = screenDC.GetClipBox( &rClipBox );    

    CRect winRect;
    GetClientRect(&winRect);

    // Set up a memdc for the update portion
    // for flicker-free drawing
    CMemDC dc(&screenDC, &winRect);

    // Let the control draw itself 
    DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, (LPARAM)0);

    if(isRectDrawed())
    {              
        long nLeft, nTop, nWidth, nHeight;        

        // get the rectangle location on the screen DC
        GetRectValuesObject(&nLeft, &nTop, &nWidth, &nHeight);             
        CRect rScreen(nLeft,nTop, nLeft+nWidth, nTop+nHeight);
        
        // see what part of the rectangle is in the clipping area
        CRect rArea;
        rArea.IntersectRect(&rClipBox, &rScreen);

        if(!rArea.IsRectEmpty())
        {
            // Create an in-memory DC 
            CDC dcMemory; 
            dcMemory.CreateCompatibleDC(&dc); 

            // create a bitmap for the area to paint
            CBitmap bmp;
            bmp.CreateCompatibleBitmap(&dc, rArea.Width(), rArea.Height());

            // Select the bitmap into the in-memory DC
            CBitmap* pOldBitmap = dcMemory.SelectObject(&bmp);

            // create the brush in the color we want to use
            CBrush brSelect;
            brSelect.CreateSolidBrush(RGB(0,0,255));

            // fill the bitmap with the desired color
            CRect rBitmap(0, 0, rArea.Width(), rArea.Height());
            dcMemory.FillRect( &rBitmap, &brSelect);

            // release the brush
            brSelect.DeleteObject();

            // set the desired transparency
            long lTransparency = 25; // 0 - 100  15=light
            BYTE SourceConstantAlpha = (BYTE)(lTransparency*255 / 100);
     
            // Copy the bits from the in-memory DC into the on-screen DC using AlphaBlend
            BLENDFUNCTION blend;
            blend.BlendOp = AC_SRC_OVER; 
            blend.BlendFlags = 0;
            blend.SourceConstantAlpha = SourceConstantAlpha; 
            blend.AlphaFormat = 0x00; // AC_SRC_ALPHA = 0x01 

            ::AlphaBlend(dc.m_hDC, 
                         rArea.left, rArea.top, rArea.Width(), rArea.Height(), 
                         dcMemory.m_hDC, 
                         rBitmap.left, rBitmap.top, rBitmap.Width(), rBitmap.Height(), 
                         blend);

            dcMemory.SelectObject(pOldBitmap);

            bmp.DeleteObject();
            dcMemory.DeleteDC();
        } 
    }    
}

Slava
Posts: 66
Joined: Fri Jun 22, 2007 4:43 pm

Re: Shade the selection area

Post by Slava » Thu Jan 14, 2010 6:15 pm

I am waiting for this functionality for a year, thanks justcode! Will this work for multiple rectangles simultaniously?? (like the highlighted regions in the .NET edition)
I will try to convert this code to Delphi if I'll get time to.

Slava

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest