tscroll.c

来自「<Win2k系统编程>源码.次数为国人自编,内容丰富,还是不错的.」· C语言 代码 · 共 1,139 行 · 第 1/3 页

C
1,139
字号
                }
        }

        /* set select fields and send TQ_SELECT */
        if (row < ptab->hdr.nrows) {
                ptab->select.startrow = row;
                ptab->select.startcell = col;
                ptab->select.nrows = nrows;
                ptab->select.ncells = ncells;
        } else {
                ptab->select.nrows = 0;
                ptab->select.startrow = 0;
                ptab->select.startcell = 0;
                ptab->select.ncells = 0;
        }

        if (bNotify) {
                gtab_sendtq(hwnd, TQ_SELECT, (long) (LPSTR) &ptab->select);
        }

        /* paint in selection */
        if (nrows > 0) {
                if (!ptab->selvisible) {
                        gtab_invertsel(hwnd, ptab, NULL);
                        ptab->selvisible = TRUE;
                }
        } else {
                if (ptab->selvisible) {
                        gtab_invertsel(hwnd, ptab, NULL);
                        ptab->selvisible = FALSE;
                }
                ptab->selvisible = FALSE;
        }
}

/***************************************************************************
 * Function: gtab_ytoline
 *
 * Purpose:
 *
 * Convert window y co-ord to a line nr
 */
int
gtab_ytoline(HWND hwnd, lpTable ptab, int y)
{
        return(y / ptab->rowheight);
}

/***************************************************************************
 * Function: gtab_xtocol
 *
 * Purpose:
 *
 * Convert window x co-ord to a cell nr
 */
int
gtab_xtocol(HWND hwnd, lpTable ptab, int x)
{
        int i;
        lpCellPos ppos;

        for (i = 0; i < ptab->hdr.ncols; i++) {
                ppos = &ptab->pcellpos[i];
                if (ppos->clipstart < ppos->clipend) {
                        if ( (x >= ppos->clipstart) && (x < ppos->clipend)) {
                                return(i);
                        }
                }
        }
        return(-1);
}


/***************************************************************************
 * Function: gtab_isborder
 *
 * Purpose:
 *
 * Check if x co-ord is 'near' (+- 2 pixels) the right border of given cell
 */
BOOL
gtab_isborder(HWND hwnd, lpTable ptab, int x, int col)
{
        
        if (abs(ptab->pcellpos[col].clipend - x) < 2) {
                return(TRUE);
        } else {
                return(FALSE);
        }
}


/***************************************************************************
 * Function: gtab_enter
 *
 * Purpose:
 *
 * Set selection and send 'TQ_ENTER' event to owner
 */
void
gtab_enter(HWND hwnd, lpTable ptab, long row, long col, long nrows,
        long ncells)
{
        int line;

        /* clear existing sel if valid and visible */
        if ((ptab->select.nrows > 0) && (ptab->selvisible == TRUE)) {

                /* only clear sel if it is different from the new one */
                if ((ptab->select.startrow != row) ||
                    (ptab->select.startcell != col) ||
                    (ptab->select.nrows != nrows) ||
                    (ptab->select.ncells != ncells)) {
                        line = gtab_rowtoline(hwnd, ptab,
                                ptab->select.startrow);
                        if (line >= 0) {
                                gtab_invertsel(hwnd, ptab, NULL);
                        }
                        ptab->selvisible = FALSE;
                }
        }

        /* set select fields and send TQ_SELECT */
        if (row < ptab->hdr.nrows) {
                ptab->select.startrow = row;
                ptab->select.startcell = col;
                ptab->select.nrows = nrows;
                ptab->select.ncells = ncells;
        } else {
                ptab->select.nrows = 0;
                ptab->select.startrow = 0;
                ptab->select.startcell = 0;
                ptab->select.ncells = 0;
        }

        /* paint in selection */
        if (nrows > 0) {
                if (!ptab->selvisible) {
                        gtab_invertsel(hwnd, ptab, NULL);
                        ptab->selvisible = TRUE;
                }
                /* do this at end because it could cause a layout-change */
                gtab_sendtq(hwnd, TQ_ENTER, (long) (LPSTR) &ptab->select);
        } else {
                if (ptab->selvisible) {
                        gtab_invertsel(hwnd, ptab, NULL);
                }
                ptab->selvisible = FALSE;
        }
}


/***************************************************************************
 * Function: gtab_trackcol
 *
 * Purpose:
 *
 * Start re-sizing a column
 */
void
gtab_trackcol(HWND hwnd, lpTable ptab, int col, int x)
{

        /* ensure we see the mouse-up */
        SetCapture(hwnd);
        ptab->trackmode = TRACK_COLUMN;
        ptab->tracknr = col;
        ptab->trackline1 = x;

        /* if line at other side of cell is visible, draw that too */
        if (ptab->pcellpos[col].start >= ptab->pcellpos[col].clipstart) {
                ptab->trackline2 = ptab->pcellpos[col].start;
        } else {
                ptab->trackline2 = -1;
        }
        gtab_drawvertline(hwnd, ptab);
}



/***************************************************************************
 * Function: gtab_press
 *
 * Purpose:
 *
 * Called on mouse-down events. decide what to start tracking.
 */
void
gtab_press(HWND hwnd, lpTable ptab, int x, int y)
{
        int cell;
        long row;

        if (ptab->trackmode != TRACK_NONE) {
                return;
        }

        /* has he grabbed a cell-edge to resize ? */
        cell = gtab_xtocol(hwnd, ptab, x);
        if (cell == -1) {
                return;
        }
        if (gtab_isborder(hwnd, ptab, x, cell)) {
                gtab_trackcol(hwnd, ptab, cell, x);
                return;
        }
        if ( (cell > 0) && gtab_isborder(hwnd, ptab, x, cell-1)) {
                gtab_trackcol(hwnd, ptab, cell, x);
                return;
        }

        /* find which line he selected */
        row = gtab_linetorow(hwnd, ptab, gtab_ytoline(hwnd, ptab, y));

        /* is he selecting a disabled fixed area ? */
        if ( (row < ptab->hdr.fixedrows) || (cell < ptab->hdr.fixedcols)) {
                if (ptab->hdr.fixedselectable == FALSE) {
                        return;
                }
        }

        /* ok, start cell selection */
        ptab->trackmode = TRACK_CELL;
        SetCapture(hwnd);

        /* record and paint new selection */
        if (ptab->hdr.selectmode & TM_ROW) {
                gtab_select(hwnd, ptab, row, 0, 1, ptab->hdr.ncols, FALSE);
        } else {
                gtab_select(hwnd, ptab, row, cell, 1, 1, FALSE);
        }
        return;
}

/***************************************************************************
 * Function: gtab_release
 *
 * Purpose:
 *
 * Called on mouse-up. complete any tracking that was happening
 */
void
gtab_release(HWND hwnd, lpTable ptab, int x, int y)
{
        lpCellPos ppos;
        lpProps pprop;
        long row;
        int cx;

        switch(ptab->trackmode) {

        case TRACK_NONE:
                return;
        
        case TRACK_COLUMN:
                /* erase marker lines */
                gtab_drawvertline(hwnd, ptab);
                ReleaseCapture();
                ptab->trackmode = TRACK_NONE;

                /* adjust cell width */
                ppos = &ptab->pcellpos[ptab->tracknr];
                cx = ptab->trackline1 - ppos->start;
                pprop = &ptab->pcolhdr[ptab->tracknr].props;
                pprop->valid |= P_WIDTH;
                pprop->width = cx;
                gtab_calcwidths(hwnd, ptab);
                gtab_setsize(hwnd, ptab);
                InvalidateRect(hwnd, NULL, TRUE);
                return;

        case TRACK_CELL:
                row = gtab_linetorow(hwnd, ptab, gtab_ytoline(hwnd, ptab, y));
                ReleaseCapture();
                ptab->trackmode = TRACK_NONE;

                /* keep the same selection. if the mouse is still
                 * in the box, select it, otherwise de-select it
                 */
                if ((row == ptab->select.startrow) &&
                  ( (ptab->hdr.selectmode & TM_ROW) ||
                    (ptab->select.startcell == gtab_xtocol(hwnd, ptab, x))) ) {

                        gtab_select(hwnd, ptab, ptab->select.startrow,
                                ptab->select.startcell,
                                ptab->select.nrows, ptab->select.ncells, TRUE);
                } else {
                        gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE);
                }
                return;
        }
}


/***************************************************************************
 * Function: gtab_move
 *
 * Purpose:
 *
 * Called on mouse-move. if tracking - adjust position, if not,
 * set correct cursor
 */
void
gtab_move(HWND hwnd, lpTable ptab, int x, int y)
{
        BOOL fOK;
        long row;
        int col;
        lpCellPos ppos;

        switch(ptab->trackmode) {

        case TRACK_NONE:
                col = gtab_xtocol(hwnd, ptab, x);
                if (col == -1) {
                        SetCursor(hNormCurs);
                        return;
                }
                if (gtab_isborder(hwnd, ptab, x, col)) {
                        SetCursor(hVertCurs);
                        return;
                }
                if ( (col > 0) && gtab_isborder(hwnd, ptab, x, col-1)) {
                        SetCursor(hVertCurs);
                        return;
                }
                SetCursor(hNormCurs);
                return;

        case TRACK_CELL:
                row = gtab_linetorow(hwnd, ptab, gtab_ytoline(hwnd, ptab, y));

                /* keep the same selection. if the mouse is still
                 * in the box, select it, otherwise de-select it
                 */
                if ((row == ptab->select.startrow) &&
                  ( (ptab->hdr.selectmode & TM_ROW) ||
                    (ptab->select.startcell == gtab_xtocol(hwnd, ptab, x))) ) {

                        if (!ptab->selvisible) {
                                gtab_invertsel(hwnd, ptab, NULL);
                                ptab->selvisible = TRUE;
                        }
                } else {
                        if (ptab->selvisible) {
                                gtab_invertsel(hwnd, ptab, NULL);
                                ptab->selvisible = FALSE;
                        }
                }
                return;
        
        case TRACK_COLUMN:
                /* check that new x is still visible/valid */
                ppos = &ptab->pcellpos[ptab->tracknr];
                fOK = FALSE;

                if (ptab->tracknr < ptab->hdr.fixedcols)  {
                        if ((x > ppos->start) && (x < ptab->winwidth)) {
                                fOK = TRUE;
                        }
                } else {
                        if ((x > ppos->clipstart) && (x < ptab->winwidth)) {
                                fOK = TRUE;
                        }
                }
                if (fOK == TRUE) {
                        gtab_drawvertline(hwnd, ptab);
                        ptab->trackline1 = x;
                        gtab_drawvertline(hwnd, ptab);
                }
                return;
        }
}

/***************************************************************************
 * Function: gtab_dblclick
 *
 * Purpose:
 *
 * dbl-click - send an TQ_ENTER event to the owner (if valid) 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?