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:

code format="bb4w" ON MOUSE PROCmouse:RETURN code Then copy the code below into your program where it will not get in the way (for example at the very end):

code format="bb4w" 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% code 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:

code format="bb4w" ON MOUSE PROCmouse:RETURN code Then copy the code below into your program where it will not get in the way (for example at the very end):

code format="bb4w" 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% code 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.