table.c

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

C
917
字号
        ptab->pcellpos = (lpCellPos) gmem_get(hHeap, sizeof(CellPos) * ncols);
        if (ptab->pcellpos == NULL) {
                return(NULL);
        }

        ptab->scrollscale = 1;
        ptab->scroll_dx = 0;
        ptab->toprow = 0;
        ptab->pdata = NULL;
        ptab->nlines = 0;
        ptab->trackmode = TRACK_NONE;

        /* we have to notify owner of the current selection
         * whenever it is changed
         */
        ptab->select.id = id;
        gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE);

        /* calc ave height/width, cell widths and min height.
         * these change only when cell properties / col count changes -
         * ie only on rebuild-header events
         */
        gtab_calcwidths(hwnd, ptab);
        return(ptab);
}

/***************************************************************************
 * Function: gtab_setsize
 *
 * Purpose:
 *
 * Set sizes that are based on window size and scroll pos
 * set:
 *      winwidth
 *      nlines
 *      cellpos start, clip start/end
 * Alloc linedata and init
 */
void
gtab_setsize(HWND hwnd, lpTable ptab)
{
        RECT rc;
        int nlines;
        HANDLE heap;
        long range, change;

        GetClientRect(hwnd, &rc);
        ptab->winwidth = rc.right - rc.left;
        nlines = (rc.bottom - rc.top) / ptab->rowheight;
        /* nlines is the number of whole lines - add one extra
         * for the partial line at the bottom
         */
        nlines += 1;

        /* alloc space for nlines of data - if nlines has changed */
        if (nlines != ptab->nlines) {
                heap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
                gtab_freelinedata(heap, ptab);
                ptab->nlines = nlines;
                if (!gtab_alloclinedata(hwnd, heap, ptab)) {
                        ptab->nlines = 0;
                        return;
                }
        }

        /* set scroll vertical range */
        range = ptab->hdr.nrows - (ptab->nlines - 1);
        if (range < 0) {
                range = 0;
                change =  -(ptab->toprow);
        } else if (ptab->toprow > range) {
                change = range - ptab->toprow;
        } else {
                change = 0;
        }
        /* the scroll range must be 16-bits for Win3
         * scale until this is true
         */
        ptab->scrollscale = 1;
        while (range > 32766) {
                ptab->scrollscale *= 16;
                range /= 16;
        }

        SetScrollRange(hwnd, SB_VERT, 0, (int) range, TRUE);
        gtab_dovscroll(hwnd, ptab, change);

        /* set horz scroll range */
        range = ptab->rowwidth - ptab->winwidth;
        if (range < 0) {
                range = 0;
                change = -(ptab->scroll_dx);
        } else if (ptab->scroll_dx > range) {
                change = range - ptab->scroll_dx;
        } else {
                change = 0;
        }
        /* horz scroll range will always be < 16 bits */
        SetScrollRange(hwnd, SB_HORZ, 0, (int) range, TRUE);
        gtab_dohscroll(hwnd, ptab, change);
}

/***************************************************************************
 * Function: gtab_calcwidths
 *
 * Purpose:
 *
 * Set column widths/height and totals (based on column props)
 * - no assumption of window size (see gtab_setsize)
 * sets avewidth,rowheight,cellpos.size,rowwidth (total of cellpos.size)
 */
void
gtab_calcwidths(HWND hwnd, lpTable ptab)
{
        int i, cxtotal, cx, ave;
        TEXTMETRIC tm, tmcol;
        HDC hdc;
        lpProps hdrprops, cellprops;
        HFONT hfont;

        hdrprops = &ptab->hdr.props;
        hdc = GetDC(hwnd);
        if (hdrprops->valid & P_FONT) {
                hfont = SelectObject(hdc, hdrprops->hFont);
        }
        GetTextMetrics(hdc, &tm);
        if (hdrprops->valid & P_FONT) {
                SelectObject(hdc, hfont);
        }
        ReleaseDC(hwnd, hdc);

        /* get width and height of average character */
        ptab->avewidth = tm.tmAveCharWidth;
        ptab->rowheight = tm.tmHeight + tm.tmExternalLeading;
        if (hdrprops->valid & P_HEIGHT) {
                ptab->rowheight = hdrprops->height;
        }

        /* set pixel width of each cell (and add up for row total)
         * based on ave width * nr chars, unless P_WIDTH set
         */
        cxtotal = 0;
        for (i = 0; i < ptab->hdr.ncols; i++) {
                cellprops = &ptab->pcolhdr[i].props;

                if (cellprops->valid & P_WIDTH) {
                        cx = cellprops->width;
                } else if (hdrprops->valid & P_WIDTH) {
                        cx = hdrprops->width;
                } else {

                        if (cellprops->valid & P_FONT) {
                                hdc = GetDC(hwnd);
                                hfont = SelectObject(hdc, cellprops->hFont);
                                GetTextMetrics(hdc, &tmcol);
                                SelectObject(hdc, hfont);
                                ReleaseDC(hwnd, hdc);
                                ave = tmcol.tmAveCharWidth;
                        } else {
                                ave = ptab->avewidth;
                        }
                        /* ave width * nchars */
                        cx =  ptab->pcolhdr[i].nchars + 1;
                        cx *= ave;
                }
                /* add 2 pixels for box lines */
                cx += 2;
                ptab->pcellpos[i].size = cx;
                cxtotal += cx;
        }
        ptab->rowwidth = cxtotal;
}

/***************************************************************************
 * Function: gtab_newsize
 *
 * Purpose:
 *
 * Called when row data + possible nrows changes.
 * other changes are ignored
 */
void
gtab_newsize(HWND hwnd, lpTable ptab)
{
        TableHdr hdr;

        /* get new row count */
        hdr = ptab->hdr;
        gtab_sendtq(hwnd, TQ_GETSIZE, (long) (LPSTR) &hdr);
        if (hdr.nrows != ptab->hdr.nrows) {
                ptab->hdr.nrows = hdr.nrows;
                gtab_setsize(hwnd, ptab);
        }

        gtab_invallines(hwnd, ptab, 0, ptab->nlines);

        InvalidateRect(hwnd, NULL, TRUE);
}

void
gtab_invallines(HWND hwnd, lpTable ptab, int start, int count)
{
        int i, j;

        for (i = start; i < start + count; i++) {
                for (j = 0; j < ptab->hdr.ncols; j++) {
                        ptab->pdata[i].pdata[j].flags = 0;
                }
        }
}

/***************************************************************************
 * Function: gtab_append
 *
 * Purpose:
 *
 * New rows have been added to the table. Adjust the scroll range and
 * position, and redraw the rows if the end of the table is currently
 * visible.
 * rows = the new total row count.
 */
void
gtab_append(HWND hwnd, lpTable ptab, int rows, DWORD id)
{
        long range;
        long oldrows;
        int line, nupdates;
        RECT rc;


        /* change to the new id */
        ptab->hdr.id = id;
        ptab->select.id = id;

        /* update the header, but remember the old nr of rows
         * so we know where to start updating
         */
        oldrows = ptab->hdr.nrows;

        /* check that the new nr of rows is not smaller. this is
         * illegal at this point and should be ignored
         */
        if (oldrows >= rows) {
                return; 
        }

        ptab->hdr.nrows = rows;

        /* set the vertical scroll range */
        range = rows - (ptab->nlines - 1);

        if (range < 0) {
                range = 0;      
        }

        /* force the scroll range into 16-bits for win 3.1 */
        ptab->scrollscale = 1;
        while (range > 32766) {
                ptab->scrollscale *= 16;
                range /= 16;
        }

        /* now set the scroll bar range and position */
        SetScrollRange(hwnd, SB_VERT, 0, (int) range, TRUE);
        if (range > 0) {
                SetScrollPos(hwnd, SB_VERT,
                        (int) (ptab->toprow / ptab->scrollscale), TRUE);
        }

        /* calculate which screen lines need to be updated - find what
         * screen line the start of the new section is at
         */
        line = gtab_rowtoline(hwnd, ptab, oldrows);
        if (line == -1) {
                /* not visible -> no more to do */
                return;
        }

        /* how many lines to update - rest of screen or nr of
         * new lines if less than rest of screen
         */
        nupdates = min((ptab->nlines - line), (int)(rows - oldrows));

        /* invalidate the screen line buffers to indicate data
         * needs to be refetch from parent window
         */
        gtab_invallines(hwnd, ptab, line, nupdates);

        /* calculate the region of the screen to be repainted -
         * left and right are same as window. top and bottom
         * need to be calculated from screen line height
         */
        
        GetClientRect(hwnd, &rc);
        rc.top += line * ptab->rowheight;
        rc.bottom = rc.top + (nupdates * ptab->rowheight);

        /* force a repaint of the updated region */
        InvalidateRect(hwnd, &rc, TRUE);
}
        


        

⌨️ 快捷键说明

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