User Tools

Site Tools


selecting_20and_20copying_20using_20the_20mouse

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.

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
selecting_20and_20copying_20using_20the_20mouse.txt · Last modified: 2018/04/16 14:33 by richardrussell