Creating a Rubber-Banding Effect with a Straight Line

When lines are drawn with a rubber-banding effect, two things happen: the original line (if one exists) is erased, and a new line is drawn in its place. This process typically takes place each time the mouse is dragged and continues until the mouse button is released. The quickest way to erase the original line (having ensured that it was drawn using mix attribute FM_XOR) is to redraw it using mix attribute FM_XOR. The following figure shows how to create this effect.

#define INCL_WININPUT
#define INCL_GPITRANSFORMS
#define INCL_GPIPRIMITIVES
#include <os2.h>
    HPS hps;                            /* Presentation-space handle  */
    LONG curr_color;

MRESULT EXPENTRY wpGeneric(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2){
    static POINTL ptlStart;             /* Starting point of line     */
    static POINTL ptlNew;               /* Ending point of line       */
    static POINTL ptlPrev;              /* Previous end point of line */
    static BOOL fDraw;                  /* Line-drawing flag          */

    switch (msg) {
        case WM_BUTTON1DOWN:            /* User begins drawing        */
           GpiSetColor(hps, CLR_GREEN);
           ptlStart.x = (LONG) (LOUSHORT(mp1));
           ptlStart.y = (LONG) (HIUSHORT(mp1));
           GpiConvert(hps, CVTC_DEVICE, CVTC_WORLD, 1L,
                    &ptlStart);
           ptlPrev.x = ptlStart.x;
           ptlPrev.y = ptlStart.y;
           GpiMove(hps, &ptlStart);
           fDraw = TRUE;
           return ((MRESULT) TRUE);

        case WM_MOUSEMOVE:              /* User draws line             */
            if (fDraw) {
                ptlNew.x = (LONG) (LOUSHORT(mp1));
                ptlNew.y = (LONG) (HIUSHORT(mp1));
                GpiConvert(hps, CVTC_DEVICE, CVTC_WORLD, 1L,  &ptlNew);
                curr_color = GpiQueryColor(hps);
                GpiSetMix(hps, FM_XOR);
                if ((ptlStart.x != ptlPrev.x)
                || (ptlStart.y != ptlPrev.y)) {
                    GpiMove(hps, &ptlStart);
                    GpiLine(hps, &ptlPrev);
                } /* if */
                if ((ptlStart.x != ptlNew.x)
                || (ptlStart.y != ptlNew.y)) {
                    GpiMove(hps, &ptlStart);
                    GpiLine(hps, &ptlNew);
                    ptlPrev.x = ptlNew.x;
                    ptlPrev.y = ptlNew.y;
                } /* if */
                GpiSetMix(hps, FM_OVERPAINT);
            } /* if */
            return ((MRESULT) TRUE);

         case WM_BUTTON1UP:              /* User stops drawing          */
            fDraw = FALSE;
            return ((MRESULT) TRUE);
    } /* switch */
} /* wpGeneric */


[Back: Drawing a Straight Line]
[Next: Drawing a Circle]