Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Copying Graphics to the Clipboard

gregscvf
Beginner
645 Views
Does anyone have a code snippet that would perform the select/copy operations automatically by program control? The default Edit menu under Quick-Win provides the Select and Copy features, however the Select Graphic is not very precise. I would like to set a predefined area for selection followed by a copy using program commands.

Also of interest, "N4=SETBKCOLORRGB(#FFFFFF)" hides the selection rectangle. So if want to see the selection, and you want a white background, you must follow the CLEARSCREEN command with "N4=SETBKCOLOR(0)".
I?m running CVF 6.6A (and now B) on a WIN 2K computer.
Greg
0 Kudos
9 Replies
Jugoslav_Dujic
Valued Contributor II
645 Views
Well, it's possible but it's tedious:
 
PROGRAM Test

USE DFLIB
USE DFWIN

IMPLICIT NONE

INTEGER::                  hBmp, hdcQW, hdcComp, iSizeImage, cClrBits, iSt, hmemBmBits, hClipboard
INTEGER(1)::               bmBits(*); POINTER(pbmBits, bmBits)
TYPE(T_BITMAPINFO)::       BI; POINTER(pBI,BI)
TYPE(T_BITMAP)::           Bmp
TYPE(WINDOWCONFIG)::       WC

iSt = GETWINDOWCONFIG(WC)
WC%NUMCOLORS=-1
WC%BITSPERPIXEL=-1
IF (.NOT.SETWINDOWCONFIG(WC)) iSt = SETWINDOWCONFIG(WC)
iSt = SETCOLORRGB(#0000FF)
iSt = RECTANGLE($GFILLINTERIOR, 20, 20, 80, 80)

!Get the DC (canvas) of child window's client area
hdcQW = GetDC(GETHWNDQQ(0))

!Create a buffer DC in memory and a bitmap of appropriate size in it
hdcComp = CreateCompatibleDC(NULL)
hBmp = CreateCompatibleBitmap(GetDC(NULL), 100, 100)
iSt = SelectObject(hdcComp, hBmp)

!Copy contents of QW window DC into buffer DC
iSt = BitBlt(hdcComp,0,0,100,100,hdcQW,0,0,SRCCOPY)
iSt = ReleaseDC(GETHWNDQQ(0), hdcQW)

!Get the bits of the bitmap
cClrBits = 16
iSizeImage=((100 * cClrBits + 31) /8) * 100

!Allocate memory for BITMAPINFO structure. It consists of BITMAPINFOHEADER
!structure followed immediately in memory by array of color bits.
hmemBmBits = GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE, iSizeImage+SIZEOF(BI%bmiHeader))
pbmBits = GlobalLock(hmemBmBits)
pBI = pbmBits

!Fill in the BITMAPINFOHEADER.
BI%bmiHeader%biSize          = SIZEOF(BI%bmiHeader)
BI%bmiHeader%biWidth         = 100
BI%bmiHeader%biHeight        = 100
BI%bmiHeader%biPlanes        = 1                  !1 plane (e.g. icons have 2)
BI%bmiHeader%biBitCount      = cClrBits           !color depth
BI%bmiHeader%biCompression   = BI_RGB             !no compression
BI%bmiHeader%biSizeImage     = iSizeImage
BI%bmiHeader%biXPelsPerMeter = 96*100/2.54+1
BI%bmiHeader%biYPelsPerMeter = 96*100/2.54+1
BI%bmiHeader%biClrImportant  = 0

!Get the bitmap bits into BI. Actual bits start at this offset--v
iSt = GetDIBits(hdcComp, hBmp, 0, 100, pbmBits+SIZEOF(BI%bmiHeader), pBI, DIB_RGB_COLORS)

!Release the resources for buffer
iSt = DeleteObject(hBmp)
iSt = DeleteDC(hdcComp)

hClipboard = OpenClipboard(GETHWNDQQ(QWIN$FRAMEWINDOW))

!This was just a nice try :-(
!iSizeImage = IMAGESIZE(0,0,100,100)
!CALL GETIMAGE(0,0,100,100,bmBits)

!Copy the contents onto clipboard
iSt = SetClipboardData(CF_DIB, hmemBmBits)

!Clean up
iSt = CloseClipboard()
iSt = GlobalUnlock(hmemBmBits)
iSt = GlobalFree(hmemBmBits)

DO
      CALL SLEEPQQ(200)
END DO

END PROGRAM Test


Steve, could someone from QuickWin team please post the format of buffer returned by GETIMAGE? It would ease such things significantly, but I don't feel like reverse-engineering it myself.

Jugoslav
0 Kudos
gregscvf
Beginner
645 Views
Hi,
TFYH,
I think we're close.
First try, didn't work.
Added "iSt = EmptyClipboard ()".
Now it copies the 100 x 100 block, but in all black.
I believe we want red rectangle with black border.
Any further help gratefully appreciated.

Greg


0 Kudos
Jugoslav_Dujic
Valued Contributor II
645 Views
Hmm, strange -- I copied & pasted the code that worked for me (CVF6.6B @ Windows 2000). Could you step through the code and see if some of the functions fail? (GetDIBits is supposed to return 100, and bits in the middle of bmBits should have value 127 (=#FF)).

Jugoslav

P.S. I didn't try the general case, so I expect problems if you try to select non-visible area of child window. Also, if scrollbars are off-zero position you might need to subtract its offsets (see GetScrollPos).
0 Kudos
gregscvf
Beginner
645 Views
Very interesting...
Under debug the program places graphics from the active CVF edit window into the clipboard. This is done properly. Can actually read the text after pasting. Non-debug still pastes a black rectangle.
The function codes: GetDIBit=100, but BmBits=#00000078 (debug or not). No other errors except GlobalUnlock=0.
Greg
0 Kudos
Jugoslav_Dujic
Valued Contributor II
645 Views
Eh, maybe I was too zealous in cleaning up:


After SetClipboardData is called, the system owns the object identified by the hMem parameter. The application can read the data, but must not free the handle or leave it locked.


Looks as if that GlobalFree was extra. (But even with it, it still worked for me in both Debug and Release).
0 Kudos
gregscvf
Beginner
645 Views
Works just fine on another computer.
Copied EXE to my computer... still doesn't work.
I ordered a new computer.
Thanks again.
Greg
0 Kudos
Jugoslav_Dujic
Valued Contributor II
645 Views
I wish I could solve my problems like that! :-).

Just a guess -- maybe it has something to do with color depth of the display?
0 Kudos
gregscvf
Beginner
645 Views
Yes...
Was 256, increased to 16-bit.
Is it the SetColorRGB?
It always seemed to work before.
Just kidding about the computer :-).
Greg
0 Kudos
Jugoslav_Dujic
Valued Contributor II
645 Views
Does it work now? It should. The problem could be that I hard-coded cClrBits to 16. GetDIBits is able to convert the bitmap to any desired color depth (that's why I had asked about contents of bmBits -- but I forgot to tell you that you have to type bmBits(10000:11000) in the debugger to see what bits are actually there). My guess, however, was that Paint (or whatever you used) was unable to cope with pasted bitmap with more colors than screen depth.

You can query actual color depth using GetDeviceCaps(GetDC(NULL), BITSPIXEL) and use that value as cClrBits.

Jugoslav
0 Kudos
Reply