=====Selecting and copying using the mouse=====
//by Richard Russell, May 2006, amended October 2009//
===== Selecting and copying text =====
Many Windows programs allow you to select a block of text by //dragging// the mouse. Typically you can then copy the selected text to the clipboard by right-clicking and selecting **Copy** from a popup menu.\\ \\ You get this functionality for free if you use an **edit box** for text input or output (either on your main window or in a dialogue box), but otherwise it's not straightforward to achieve in BASIC.\\ \\ The code below allows you to incorporate this facility very easily. It will work with almost any program that outputs (monospaced) text to the main window at ordinary text coordinates. Since it's implemented as an **ON MOUSE** routine you can often add it to a program without modifying the existing code at all.\\ \\ To use this code first add the following line near the beginning of your program:
ON MOUSE PROCmouse:RETURN
Then copy the code below into your program where it will not get in the way (for example at the very end):
DEF PROCmouse
LOCAL H%,M%,O%,P%,A$,@vdu%!24,@vdu%!32
PRIVATE V%,W%,X%,Y%,Z%
ON ERROR LOCAL RESTORE LOCAL : ERROR ERR, REPORT$
IF Z% ENDPROC
Z% = TRUE
IF INKEY(-10) THEN
SYS "GetROP2", @memhdc% TO M%
SYS "CreateSolidBrush", &FFFFFF TO H%
SYS "SelectObject", @memhdc%, H% TO O%
SYS "SetROP2", @memhdc%, 7
SYS "Rectangle", @memhdc%, V%, W%, X%, Y%
PROCtextxy(X%,Y%)
V% = X% : W% = Y%
WHILE INKEY(-10)
SYS "Rectangle", @memhdc%, V%, W%, X%, Y%
PROCtextxy(X%,Y%)
Y% += (1+2*(W%>Y%))*@vdu%!220
SYS "Rectangle", @memhdc%, V%, W%, X%, Y%
SYS "InvalidateRect", @hwnd%, 0, 0
WAIT 1
ENDWHILE
SYS "SelectObject", @memhdc%, O%
SYS "DeleteObject", H%
SYS "SetROP2", @memhdc%, M%
ENDIF
IF INKEY(-12) AND (X%<>V%) THEN
SYS "CreatePopupMenu" TO M%
SYS "AppendMenu", M%, 0, 3, "&Copy"
SYS "GetCursorPos", ^O%
IF FNtrackpopupmenu(M%,256,O%,P%) = 3 THEN
IF V% > X% SWAP V%,X%
IF W% > Y% SWAP W%,Y%
FOR P% = W% TO Y%-1 STEP @vdu%!220
FOR O% = V% TO X%-1 STEP @vdu%!216
A$ += GET$(O% DIV @vdu%!216,P% DIV @vdu%!220)
NEXT O%
WHILE RIGHT$(A$)=" " : A$ = LEFT$(A$) : ENDWHILE
IF (Y%-W%) > @vdu%!220 A$ += CHR$13+CHR$10
NEXT P%
SYS "GlobalAlloc", &2000, LEN(A$)+1 TO H%
SYS "GlobalLock", H% TO P%
$$P% = A$
SYS "GlobalUnlock", H%
SYS "OpenClipboard", @hwnd%
SYS "EmptyClipboard"
SYS "SetClipboardData", 1, H%
SYS "CloseClipboard"
ENDIF
SYS "DestroyMenu", M%
ENDIF
Z% = FALSE
ENDPROC
DEF PROCtextxy(RETURN X%, RETURN Y%)
SYS "GetCursorPos", ^X%
SYS "ScreenToClient", @hwnd%, ^X%
X% = (X% DIV @vdu%!216) * @vdu%!216
Y% = (Y% DIV @vdu%!220) * @vdu%!220
ENDPROC
DEF FNtrackpopupmenu(H%,F%,X%,Y%)
LOCAL M%, O%, P%, T%
DIM P% LOCAL 60
[OPT 2
.T%
push 0
push @hwnd%
push 0
push Y%
push X%
push F%
push H%
call "TrackPopupMenu"
ret 16
.M% cmp dword [esp+8],&500 : jz T%
pop eax : push [^O%] : push eax
jmp "CallWindowProc"
]
SYS "GetWindowLong", @hwnd%, -4 TO O%
SYS "SetWindowLong", @hwnd%, -4, M%
SYS "SendMessage", @hwnd%, &500, 0, 0 TO T%
SYS "SetWindowLong", @hwnd%, -4, O%
SYS "SendMessage", @hwnd%, 0, 0, 0
= T%
Once this code has been added to your program you can highlight a rectangular block of text by //dragging// the mouse over it. A right mouse-click will display a popup menu containing the **Copy** item. Clicking on that will copy the selected text to the clipboard.
===== Selecting and copying graphics =====
The code below implements a similar facility to the above, but allows you to select and copy graphics rather than text.\\ \\ To use this code first add the following line near the beginning of your program:
ON MOUSE PROCmouse:RETURN
Then copy the code below into your program where it will not get in the way (for example at the very end):
DEF PROCmouse
LOCAL D%,H%,M%,O%,P%
PRIVATE V%,W%,X%,Y%,Z%
ON ERROR LOCAL RESTORE LOCAL : ERROR ERR, REPORT$
IF Z% ENDPROC
Z% = TRUE
IF INKEY(-10) THEN
SYS "GetROP2", @memhdc% TO M%
SYS "GetStockObject", 5 TO H%
SYS "CreatePen", 1, 1, &FFFFFF TO P%
SYS "SelectObject", @memhdc%, H% TO D%
SYS "SelectObject", @memhdc%, P% TO O%
SYS "SetROP2", @memhdc%, 7
SYS "Rectangle", @memhdc%, V%, W%, X%, Y%
PROCmousexy(X%,Y%)
V% = X% : W% = Y%
WHILE INKEY(-10)
SYS "Rectangle", @memhdc%, V%, W%, X%, Y%
PROCmousexy(X%,Y%)
SYS "Rectangle", @memhdc%, V%, W%, X%, Y%
SYS "InvalidateRect", @hwnd%, 0, 0
WAIT 1
ENDWHILE
SYS "SelectObject", @memhdc%, D%
SYS "SelectObject", @memhdc%, O%
SYS "DeleteObject", P%
SYS "SetROP2", @memhdc%, M%
ENDIF
IF INKEY(-12) AND (X%<>V%) THEN
SYS "CreatePopupMenu" TO M%
SYS "AppendMenu", M%, 0, 3, "&Copy"
SYS "GetCursorPos", ^O%
IF FNtrackpopupmenu(M%,256,O%,P%) = 3 THEN
IF V% > X% SWAP V%,X%
IF W% > Y% SWAP W%,Y%
SYS "CreateCompatibleDC", @memhdc% TO D%
SYS "CreateCompatibleBitmap", @memhdc%, X%-V%-2, Y%-W%-2 TO H%
SYS "SelectObject", D%, H% TO O%
SYS "BitBlt", D%, 0, 0, X%-V%-2, Y%-W%-2, @memhdc%, V%+1, W%+1, &CC0020
SYS "SelectObject", D%, O%
SYS "DeleteDC", D%
SYS "OpenClipboard", @hwnd%
SYS "EmptyClipboard"
SYS "SetClipboardData", 2, H%
SYS "CloseClipboard"
ENDIF
SYS "DestroyMenu", M%
ENDIF
Z% = FALSE
ENDPROC
DEF PROCmousexy(RETURN X%, RETURN Y%)
SYS "GetCursorPos", ^X%
SYS "ScreenToClient", @hwnd%, ^X%
ENDPROC
DEF FNtrackpopupmenu(H%,F%,X%,Y%)
LOCAL M%, O%, P%, T%
DIM P% LOCAL 60
[OPT 2
.T%
push 0
push @hwnd%
push 0
push Y%
push X%
push F%
push H%
call "TrackPopupMenu"
ret 16
.M% cmp dword [esp+8],&500 : jz T%
pop eax : push [^O%] : push eax
jmp "CallWindowProc"
]
SYS "GetWindowLong", @hwnd%, -4 TO O%
SYS "SetWindowLong", @hwnd%, -4, M%
SYS "SendMessage", @hwnd%, &500, 0, 0 TO T%
SYS "SetWindowLong", @hwnd%, -4, O%
SYS "SendMessage", @hwnd%, 0, 0, 0
= T%
Once this code has been added to your program you can select a rectangular region by //dragging// the mouse over it. A right mouse-click will display a popup menu containing the **Copy** item. Clicking on that will copy the graphics in the selected region to the clipboard.