gbClientCapture (Discussion)
#1
I decided to break the gbScroller app into two parts. The first is posted in the forum as gbClientCapture.

It captures the area under the transparent dialog client, merging each new capture into a horizontal image for subsequent scrolling. I've not yet written the scrolling app.

The area between the Toolbar and Statusbar is captured and merged into a horizontal image.

[Image: capture.jpg]

Some new features come to mind:

1. allow using the arrow keys to more accurately position the dialog
2. with transparency, the resize with a mouse ability is limited to the caption and toolbar. Not sure why but I know I don't like it.

Not a feature, but I notice there is a tiny gap between the caption and toolbar. I'm not sure why. I thought the toolbar by default would be positioned immediately next to the caption.

And, another thing, I tweaked the various dimensions to make sure the client area is captured, without overlapping the toolbar, statusbar and dialog borders. But it seems to me that I should have been able to do a more exact dimensioning of the capture positioning/size.

Here's how I envision this working.

1. Call up the electronic copy of the music (PDF in this example).
2. Place gbClientCapture over the first row of music (resize as needed)
3. Click "Copy"
4. Scroll the PDF upwards until the next row of music is under gbClientCapture (that should be easier than moving the dialog itself.
5. Click "Copy"
6. Repeat until all rows of music are captured and placed in the "merge.bmp" file.

In this example, the Adele music sheet PDF is displayed vertically in my browser.  The gbClientCapture is positioned over the first row, ready for "Copy".  Then, instead of moving the dialog to a new position, I scroll the PDF upwards until the next row of music is visible under the dialog client area. Repeat Copying untill all rows of music are captured. With each capture the "merge.bmp" file is updated to contain the most recent capture.

[Image: capture2.jpg]
Reply
#2
Hey! Hey!

It's the 2-pixel divider part of the toolbar's rendering but you didn't fill it using your custom draw handler it only painted the provided rect leaving it's background color white and becomes transparent. Just remove it.

Code:
'-add styles to remove the 3D borders and the 2-pixel top highlight/divider.
CONTROL ADD TOOLBAR, hDlg, %IDC_Toolbar, "", 0,0,0,0, %TBSTYLE_FLAT OR %CCS_NODIVIDER
Reply
#3
I was looking at the resizing cursor issue.  For sure the transparency is messing with the WM_NCHITTEST 'ing for the borders and the status bar grip sizer.   For giggles I reverted back to the classic frame, but this introduced flicker issues with your toolbar.    

Added  %WM_CLIPCHILDREN to your dialog and under WM_INITDIALOG... 
Code:
'-disable DWM non-client rendering for classic borders
         LOCAL policy AS LONG
         policy = %DWMNCRP_DISABLED
         LOCAL lReturn AS LONG
         CALL DwmSetWindowAttribute(hDlg, %DWMWA_NCRENDERING_POLICY, BYVAL VARPTR(policy), 4)
         '-force frame redraw to apply changes
         SetWindowPos hDlg, 0, 0, 0, 0, 0, %SWP_FRAMECHANGED OR %SWP_NOMOVE OR %SWP_NOSIZE OR %SWP_NOZORDER
         RedrawWindow hDlg, BYVAL 0, BYVAL 0, %RDW_FRAME OR %RDW_INVALIDATE         

I tried adding a double buffer to your toolbar drawing but no luck so far reducing the flicker while resizing.
Reply
#4
I was thinking it would be easier to create a region hole instead to avoid going down a deep rabbit hole to resolve your sizing issue. OK, so here is a snippet I lifted from an old post.  It has one side effect...  

Code:
'
'-snippet taken from Greg Turgeon post 5 Aug 2007 PowerBASIC forum
' https://forum.powerbasic.com/forum/user-to-user-discussions/powerbasic-for-windows/14801-how-to-make-a-hole?p=205890#post205890

#COMPILE EXE
#DIM ALL
#INCLUDE "WIN32API.INC"

#RESOURCE MANIFEST, 1,      "icons\xptheme_dpiaware.xml"

'--------------------------------------------------------------------------------------------------
'
'--------------------------------------------------------------------------------------------------
FUNCTION PBMAIN&()
    LOCAL hDlg, x, y, lwide, lhigh AS LONG
    DIALOG NEW PIXELS, 0,"", , , 496, 160, %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_CAPTION OR %WS_THICKFRAME,,  TO hDlg
    DIALOG GET CLIENT hDlg TO x, y
    DIALOG SHOW MODAL hDlg, CALL DlgMain&()
END FUNCTION

'--------------------------------------------------------------------------------------------------
'
'--------------------------------------------------------------------------------------------------
CALLBACK FUNCTION DlgMain&()
    STATIC captionHigh AS LONG
    LOCAL hRgn, lwide, lhigh, clientWide, clientHigh AS LONG
    LOCAL rc AS RECT, p() AS POINTL

    SELECT CASE AS LONG CBMSG

        CASE %WM_INITDIALOG
          captionHigh = GetSystemMetrics(%SM_CYCAPTION)
          SetWindowPos CBHNDL, %HWND_TOPMOST, 0, 0, 0, 0, %SWP_NOSIZE OR %SWP_NOMOVE
          DIALOG GET SIZE CBHNDL TO lwide, lhigh
          DIALOG GET CLIENT CBHNDL TO clientWide, clientHigh
          SetRect rc, 10, (lhigh-clientHigh)+captionHigh*2, lwide-10, lhigh-captionHigh
          hRgn = CreateRectRgn(rc.nLeft, rc.nTop, rc.nRight, rc.nBottom)
          CreateHole CBHNDL, hRgn, %TRUE

        CASE %WM_SIZE
            DIALOG GET SIZE CBHNDL TO lwide, lhigh
            DIALOG GET CLIENT CBHNDL TO clientWide, clientHigh
            SetRect rc, 10, (lhigh-clientHigh)+captionHigh*2, lwide-10, lhigh-captionHigh
            hRgn = CreateRectRgn(rc.nLeft, rc.nTop, rc.nRight, rc.nBottom)
            CreateHole CBHNDL, hRgn, %TRUE


    END SELECT
END FUNCTION

'--------------------------------------------------------------------------------------------------
'
'--------------------------------------------------------------------------------------------------
FUNCTION CreateHole&(BYVAL hWnd AS LONG, BYVAL hRGN AS LONG, BYVAL Action AS LONG)
    LOCAL windowRect AS RECT, hWindowRgn, hHoleRgn, hThisRgn AS LONG
    GetWindowRect hWnd, windowRect
    hWindowRgn = CreateRectRgn(0,0,WindowRect.nRight, WindowRect.nBottom)
    hHoleRgn = CreateRectRgn(0,0,0,0)
    IF Action THEN
       hThisRgn = CreateRectRgn (0,0,0,0)
       CombineRgn hThisRgn, hRGN, 0&, %RGN_COPY
    ELSE
       CombineRgn hThisRgn, hRGN, 0&, %RGN_OR
    END IF
    CombineRgn hHoleRgn, hThisRgn, hWindowRgn, %RGN_XOR
    SetWindowRgn hWnd, hHoleRgn, %TRUE
END FUNCTION

   
Reply
#5
Howdy, Jules!

Thanks!  I'd never noticed CCS_NoDivider before.  Searching gbThreads, I do not see CCS_NoDivider mentioned in any thread! But, it does what I wanted!

As for the region approach, it does restore resizing.

What is the drawback that you refer to?
Reply
#6
Hey Gary,
 
The DWM detects the custom region and disables theming for that window to avoid conflicts with shaped windows and falls back to the classic look for the frame/title bar. This is a known Win32 limitation when using SetWindowRgn.

Here, try this other version, this time using GDI+ , as long as you keep enough margin the sizing cursors will activate.  

Code:
#COMPILE EXE
#DIM ALL
#INCLUDE "WIN32API.INC"
#INCLUDE "gdipDash0713.inc" '<-replace with Jose or you own GDI+ include file.

CALLBACK FUNCTION DlgMain()
    STATIC captionHigh AS LONG
    STATIC keyColor AS LONG
    LOCAL hBrushBg, hBrushKey AS DWORD
    LOCAL lwide, lhigh, clientWide, clientHigh AS LONG
    LOCAL rcWindow AS RECT
    LOCAL rcHoleClient AS RECT
    LOCAL rcClient AS RECT
    LOCAL ps AS PAINTSTRUCT
    LOCAL hDC AS DWORD
    LOCAL frameX, frameY AS LONG


    SELECT CASE AS LONG CB.MSG

        CASE %WM_INITDIALOG
            captionHigh = GetSystemMetrics(%SM_CYCAPTION)
            frameX = GetSystemMetrics(%SM_CXFRAME)
            frameY = GetSystemMetrics(%SM_CYFRAME)
            keyColor = RGB(255, 0, 255) ' <-use Magenta as key color
            SetWindowPos CB.HNDL, %HWND_TOPMOST, 0, 0, 0, 0, %SWP_NOSIZE OR %SWP_NOMOVE
            SetLayeredWindowAttributes CB.HNDL, keyColor, 0, %LWA_COLORKEY
            '-force repaint
            InvalidateRect CB.HNDL, BYVAL %NULL, %TRUE

        CASE %WM_SIZE
            InvalidateRect CB.HNDL, BYVAL %NULL, %TRUE

        CASE %WM_ERASEBKGND
            FUNCTION = 1 :EXIT FUNCTION

         CASE %WM_PAINT
            hDC = BeginPaint(CB.HNDL, ps)
                DIALOG GET SIZE CB.HNDL TO lwide, lhigh
                DIALOG GET CLIENT CB.HNDL TO clientWide, clientHigh
                GetClientRect CB.HNDL, rcClient
                '-calc hole in window coordinates
                ' note: tweak your margins, left +10, right -25, bottom -25 to allow cursor hit testing
                SetRect rcWindow, 10, (lhigh - clientHigh) + captionHigh * 2, lwide - 25, lhigh - captionHigh - 25
                '-convert our hole to client coordinates
                SetRect rcHoleClient, rcWindow.nLeft - frameX, rcWindow.nTop - (captionHigh + frameY), rcWindow.nRight - frameX, rcWindow.nBottom - (captionHigh + frameY)
                '-fill entire client with system dialog background color
                hBrushBg = CreateSolidBrush(GetSysColor(%COLOR_3DFACE))
                FillRect hDC, rcClient, hBrushBg
                DeleteObject hBrushBg
                '-now fill hole with key color for transparency
                hBrushKey = CreateSolidBrush(keyColor)
                FillRect hDC, rcHoleClient, hBrushKey
                DeleteObject hBrushKey
            EndPaint CB.HNDL, ps
            FUNCTION = 0 :EXIT FUNCTION
    END SELECT
END FUNCTION

'--------------------------------------------------------------------------------------------------
'
'--------------------------------------------------------------------------------------------------
FUNCTION PBMAIN() AS LONG
    LOCAL hDlg AS LONG

    LOCAL token AS DWORD
    '-start GDI+
    IF StartGDIplus(BYREF token) THEN
        MSGBOX "Failed to start GDI+", , "Error"
        EXIT FUNCTION
    END IF

    DIALOG NEW PIXELS, 0, "Square Hole Demo", , , 496, 160, %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_CAPTION OR %WS_THICKFRAME, %WS_EX_LAYERED TO hDlg
    DIALOG SHOW MODAL hDlg, CALL DlgMain

    '-stop GDI+
    StopGDIplus token
END FUNCTION
Reply
#7
Howdy, Jules!

Thanks for the additional code - GDI+ version.  I'm working on integrating what you showed into my code - but it's about 1am here and I'm toast for the night. Will return in the morning!
Reply
#8
And Gary, just a note about the %WS_MAZIMIZEBOX style, seems there is an issue on the win32 level recovering from a restore using any of techniques we both used except for the Greg Turgeon snippet version that uses the classic theme.
Reply
#9
Howdy, Jules!

I haven't forgotten you! Just having to do a few household tasks for the wife! It may be a couple of hours before I'm back online.

I have integrated your last code and it's working mostly fine. I've added the arrow-key positioning, simplified some of your WM_Paint code. I don't have the capture working quite right - a few pixels off. Including a manifest causes the toolbar to go black. I'll post something when I get back later.

Thanks again for your posts. I'm definitely happier with getting back the resizing capability. People would have whined about it! Smile
Reply
#10
gbClientCapture v2.0 posted in the source code forums (looks the same, just some code updates).

Changes:
1. Suggestion by Jules, where a hole in the client area is made transparent instead of the entire client area, thus letting the dialog respond normally to resizing.  Thanks Jules!
2. Captured image size shows on Statusbar
3. Up/Down/Left/Right arrows will move the dialog for precision positioning
4. Raised the icon sizes to 48px and changed the font so it is NOT bold.
5. Shortcuts C-Copy N-New V-View ESC-exit
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)