《windows程序设计》学习_4:文本输出,加滚动条

//总行数

#define NUMLINES  ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))



struct

{

    int Index ;

    TCHAR* szLabel;

    TCHAR* szDesc ;



}

//结构体数组

sysmetrics [] =

        

{

        

    SM_CXSCREEN,            TEXT ("SM_CXSCREEN"),            TEXT ("Screen width in pixels"),        

    SM_CYSCREEN,            TEXT ("SM_CYSCREEN"),            TEXT ("Screen height in pixels"),       

    SM_CXVSCROLL,            TEXT ("SM_CXVSCROLL"),            TEXT ("Vertical scroll width"),        

    SM_CYHSCROLL,            TEXT ("SM_CYHSCROLL"),            TEXT ("Horizontal scroll height"),        

    SM_CYCAPTION,            TEXT ("SM_CYCAPTION"),            TEXT ("Caption bar height"),        

    SM_CXBORDER,            TEXT ("SM_CXBORDER"),            TEXT ("Window border width"),        

    SM_CYBORDER,            TEXT ("SM_CYBORDER"),            TEXT ("Window border height"),        

    SM_CXFIXEDFRAME,        TEXT ("SM_CXFIXEDFRAME"),        TEXT ("Dialog window frame width"),        

    SM_CYFIXEDFRAME,        TEXT ("SM_CYFIXEDFRAME"),        TEXT ("Dialog window frame height"),        

    SM_CYVTHUMB,            TEXT ("SM_CYVTHUMB"),            TEXT ("Vertical scroll thumb height"),        

    SM_CXHTHUMB,            TEXT ("SM_CXHTHUMB"),            TEXT ("Horizontal scroll thumb width"),        

    SM_CXICON,                TEXT ("SM_CXICON"),                TEXT ("Icon width"),        

    SM_CYICON,                TEXT ("SM_CYICON"),                TEXT ("Icon height"),        

    SM_CXCURSOR,            TEXT ("SM_CXCURSOR"),            TEXT ("Cursor width"),        

    SM_CYCURSOR,            TEXT ("SM_CYCURSOR"),            TEXT ("Cursor height"),        

    SM_CYMENU,                TEXT ("SM_CYMENU"),                TEXT ("Menu bar height"),        

    SM_CXFULLSCREEN,        TEXT ("SM_CXFULLSCREEN"),        TEXT ("Full screen client area width"),        

    SM_CYFULLSCREEN,        TEXT ("SM_CYFULLSCREEN"),        TEXT ("Full screen client area height"),        

    SM_CYKANJIWINDOW,        TEXT ("SM_CYKANJIWINDOW"),        TEXT ("Kanji window height"),        

    SM_MOUSEPRESENT,        TEXT ("SM_MOUSEPRESENT"),        TEXT ("Mouse present flag"),        

    SM_CYVSCROLL,            TEXT ("SM_CYVSCROLL"),            TEXT ("Vertical scroll arrow height"),        

    SM_CXHSCROLL,            TEXT ("SM_CXHSCROLL"),            TEXT ("Horizontal scroll arrow width"),        

    SM_DEBUG,                TEXT ("SM_DEBUG"),                TEXT ("Debug version flag"),        

    SM_SWAPBUTTON,            TEXT ("SM_SWAPBUTTON"),            TEXT ("Mouse buttons swapped flag"),        

    SM_CXMIN,                TEXT ("SM_CXMIN"),                TEXT ("Minimum window width"),        

    SM_CYMIN,                TEXT ("SM_CYMIN"),                TEXT ("Minimum window height"),        

    SM_CXSIZE,                TEXT ("SM_CXSIZE"),                TEXT ("Min/Max/Close button width"),        

    SM_CYSIZE,                TEXT ("SM_CYSIZE"),                TEXT ("Min/Max/Close button height"),        

    SM_CXSIZEFRAME,            TEXT ("SM_CXSIZEFRAME"),        TEXT ("Window sizing frame width"),        

    SM_CYSIZEFRAME,            TEXT ("SM_CYSIZEFRAME"),        TEXT ("Window sizing frame height"),        

    SM_CXMINTRACK,            TEXT ("SM_CXMINTRACK"),            TEXT ("Minimum window tracking width"),        

    SM_CYMINTRACK,            TEXT ("SM_CYMINTRACK"),            TEXT ("Minimum window tracking height"),        

    SM_CXDOUBLECLK,            TEXT ("SM_CXDOUBLECLK"),        TEXT ("Double click x tolerance"),        

    SM_CYDOUBLECLK,            TEXT ("SM_CYDOUBLECLK"),        TEXT ("Double click y tolerance"),        

    SM_CXICONSPACING,        TEXT ("SM_CXICONSPACING"),        TEXT ("Horizontal icon spacing"),        

    SM_CYICONSPACING,        TEXT ("SM_CYICONSPACING"),        TEXT ("Vertical icon spacing"),        

    SM_MENUDROPALIGNMENT,    TEXT ("SM_MENUDROPALIGNMENT"),    TEXT ("Left or right menu drop"),        

    SM_PENWINDOWS,            TEXT ("SM_PENWINDOWS"),            TEXT ("Pen extensions installed"),        

    SM_DBCSENABLED,            TEXT ("SM_DBCSENABLED"),        TEXT ("Double-Byte Char Set enabled"),        

    SM_CMOUSEBUTTONS,        TEXT ("SM_CMOUSEBUTTONS"),        TEXT ("Number of mouse buttons"),       

    SM_SECURE,                TEXT ("SM_SECURE"),                TEXT ("Security present flag"),        

    SM_CXEDGE,                TEXT ("SM_CXEDGE"),                TEXT ("3-D border width"),        

    SM_CYEDGE,                TEXT ("SM_CYEDGE"),                TEXT ("3-D border height"),        

    SM_CXMINSPACING,        TEXT ("SM_CXMINSPACING"),        TEXT ("Minimized window spacing width"),        

    SM_CYMINSPACING,        TEXT ("SM_CYMINSPACING"),        TEXT ("Minimized window spacing height"),        

    SM_CXSMICON,            TEXT ("SM_CXSMICON"),            TEXT ("Small icon width"),       

    SM_CYSMICON,            TEXT ("SM_CYSMICON"),            TEXT ("Small icon height"),        

    SM_CYSMCAPTION,            TEXT ("SM_CYSMCAPTION"),        TEXT ("Small caption height"),        

    SM_CXSMSIZE,            TEXT ("SM_CXSMSIZE"),            TEXT ("Small caption button width"),        

    SM_CYSMSIZE,            TEXT ("SM_CYSMSIZE"),            TEXT ("Small caption button height"),        

    SM_CXMENUSIZE,            TEXT ("SM_CXMENUSIZE"),            TEXT ("Menu bar button width"),        

    SM_CYMENUSIZE,            TEXT ("SM_CYMENUSIZE"),            TEXT ("Menu bar button height"),        

    SM_ARRANGE,                TEXT ("SM_ARRANGE"),            TEXT ("How minimized windows arranged"),        

    SM_CXMINIMIZED,            TEXT ("SM_CXMINIMIZED"),        TEXT ("Minimized window width"),        

    SM_CYMINIMIZED,            TEXT ("SM_CYMINIMIZED"),        TEXT ("Minimized window height"),        

    SM_CXMAXTRACK,            TEXT ("SM_CXMAXTRACK"),            TEXT ("Maximum draggable width"),        

    SM_CYMAXTRACK,            TEXT ("SM_CYMAXTRACK"),            TEXT ("Maximum draggable height"),        

    SM_CXMAXIMIZED,            TEXT ("SM_CXMAXIMIZED"),        TEXT ("Width of maximized window"),        

    SM_CYMAXIMIZED,            TEXT ("SM_CYMAXIMIZED"),        TEXT ("Height of maximized window"),        

    SM_NETWORK,                TEXT ("SM_NETWORK"),            TEXT ("Network present flag"),        

    SM_CLEANBOOT,            TEXT ("SM_CLEANBOOT"),            TEXT ("How system was booted"),        

    SM_CXDRAG,                TEXT ("SM_CXDRAG"),                TEXT ("Avoid drag x tolerance"),        

    SM_CYDRAG,                TEXT ("SM_CYDRAG"),                TEXT ("Avoid drag y tolerance"),        

    SM_SHOWSOUNDS,            TEXT ("SM_SHOWSOUNDS"),            TEXT ("Present sounds visually"),        

    SM_CXMENUCHECK,            TEXT ("SM_CXMENUCHECK"),        TEXT ("Menu check-mark width"),        

    SM_CYMENUCHECK,            TEXT ("SM_CYMENUCHECK"),        TEXT ("Menu check-mark height"),        

    SM_SLOWMACHINE,            TEXT ("SM_SLOWMACHINE"),        TEXT ("Slow processor flag"),        

    SM_MIDEASTENABLED,        TEXT ("SM_MIDEASTENABLED"),        TEXT ("Hebrew and Arabic enabled flag"),        

    SM_MOUSEWHEELPRESENT,    TEXT ("SM_MOUSEWHEELPRESENT"),    TEXT ("Mouse wheel present flag"),        

    SM_XVIRTUALSCREEN,        TEXT ("SM_XVIRTUALSCREEN"),        TEXT ("Virtual screen x origin"),        

    SM_YVIRTUALSCREEN,        TEXT ("SM_YVIRTUALSCREEN"),        TEXT ("Virtual screen y origin"),        

    SM_CXVIRTUALSCREEN,     TEXT ("SM_CXVIRTUALSCREEN"),    TEXT ("Virtual screen width"),        

    SM_CYVIRTUALSCREEN,        TEXT ("SM_CYVIRTUALSCREEN"),    TEXT ("Virtual screen height"),        

    SM_CMONITORS,            TEXT ("SM_CMONITORS"),            TEXT ("Number of monitors"),        

    SM_SAMEDISPLAYFORMAT,    TEXT ("SM_SAMEDISPLAYFORMAT"),    TEXT ("Same color format flag")

        

} ;
#include <windows.h>

#include "sysmets.h"



LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);



int WINAPI WinMain(HINSTANCE hInstance,        //当前实例句柄

                   HINSTANCE hPrevInstance, //先前实例句柄

                   LPSTR lpCmdLine,            //命令行

                   int iCmdShow)            //显示状态

{

    static TCHAR szAppName[] = TEXT("显示系统内容");

    //窗口句柄

    HWND hwnd;

    //消息

    MSG msg;

    //窗口类

    WNDCLASS wndclass;

    //窗口风格:当移动窗口或者改变大小时重绘窗口

    wndclass.style           =  CS_HREDRAW | CS_VREDRAW;

    //指明回调函数

    wndclass.lpfnWndProc   = WndProc;

    //额外的比特用来确认下一个窗口类的位置,暂时不用

    wndclass.cbClsExtra    = 0;

    //额外的比特用来确认下一个窗口实例的位置,暂时不用

    wndclass.cbWndExtra    = 0;

    //实例句柄

    wndclass.hInstance     = hInstance;

    //装载图标

    wndclass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);

    //装载光标

    wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW);

    //背景为白色

    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);

    //菜单:暂时没有

    wndclass.lpszMenuName  = NULL;

    //窗口类名

    wndclass.lpszClassName = szAppName;



    //注册窗口

    if(!RegisterClass(&wndclass))

    {

        return -1;

    }



    //创建窗口

    hwnd = CreateWindow(szAppName,                //窗口类的名称,必须是已经注册的

                        TEXT("系统内容"),        //窗口标题

                        WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,    //窗口风格,加入滚动条

                        CW_USEDEFAULT,            //X坐标

                        CW_USEDEFAULT,            //Y坐标

                        CW_USEDEFAULT,            //宽度

                        CW_USEDEFAULT,            //高度

                        NULL,                    //父窗口句柄

                        NULL,                    //菜单窗口句柄

                        hInstance,                //高级版本的windos忽略

                        NULL);                    



    //显示窗口

    //ShowWindow(hwnd,SW_SHOWNA);

    ShowWindow (hwnd, iCmdShow);



    //更新窗口

    UpdateWindow(hwnd);



    //消息循环

    while(GetMessage(&msg,NULL,0,0))

    {

        

        TranslateMessage(&msg);

        //将消息给窗口

        DispatchMessage(&msg);



    }



    return msg.wParam;



}



LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    //字符的宽度,大写字母宽度,字符高度

    static int    cxChar, cxCaps, cyChar ;

    //窗口大小

    static int cxClient, cyClient ;

    //最大宽度

    static int iMaxWidth;

    //滚动条位置

    static int iVertPos,iHorzPos,iPaintBeg,iPaintEnd;

    HDC hdc;

    //该变量用于索引sysmets.h中定义的结构体数组sysmetrics[]的每个元素

    int i;

    //输出文本的位置

    int x,y;

    //绘图结构

    PAINTSTRUCT ps;

    //这个结构包含了滚动条的信息

    //通过SetScrollInfo函数设置信息,通过 GetScrollInfo 函数获取信息

    SCROLLINFO si;

    //字符串

    TCHAR szBuffer [10];

    //字体信息结构

    TEXTMETRIC  tm;

    switch(message)

    {

    case WM_CREATE:

        hdc = GetDC(hwnd);

        //取得内定系统字体的文字大小,存在放在tm里

        GetTextMetrics (hdc, &tm);

        //平均字符宽

        cxChar = tm.tmAveCharWidth ;

        //大写字母的平均宽度

        cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;

        //字符总高度:高度+行间距

        cyChar = tm.tmHeight + tm.tmExternalLeading ;



        ReleaseDC(hwnd,hdc);

        //最大跨度 = 40个字符+22个大写字母

        iMaxWidth = 40*cxChar+22*cxCaps;

        return 0;

    case WM_SIZE:

        cxClient = LOWORD (lParam) ;        

        cyClient = HIWORD (lParam) ;   

        //设置垂直滚动条信息

        //结构体的大小

        si.cbSize  = sizeof(si);

        //指明将要设置和获取的参数:这里是最大最小值组成的范围和页面的大小

        si.fMask = SIF_RANGE | SIF_PAGE ;

        //滚动条位置的最小值

        si.nMin = 0;

        //滚动条位置的最大值

        si.nMax = NUMLINES - 1 ;

        //页面大小

        si.nPage = cyClient / cyChar ;

        //设置滚动条的参数

        SetScrollInfo(hwnd, SB_VERT,&si,TRUE);



        //设置水平滚动条信息

        si.cbSize  = sizeof(si);

        si.fMask = SIF_RANGE | SIF_PAGE ;

        si.nMin = 0;

        si.nMax = 2+ iMaxWidth/cxChar ;

        si.nPage = cxClient / cxChar ;

        SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;



        return 0; 

        

    case WM_PAINT:

        hdc = BeginPaint (hwnd, &ps) ;



        si.cbSize = sizeof(si);

        si.fMask = SIF_POS;

        GetScrollInfo(hwnd,SB_VERT,&si);

        iVertPos = si.nPos;

        GetScrollInfo(hwnd,SB_HORZ,&si);

        iHorzPos = si.nPos;

        //max(0,当前位置+需要绘图的矩形区的最高点/字符的高度)

        //iPaintBeg = max(0,iVertPos+ps.rcPaint.top/cyChar);

        iPaintBeg = max(0,iVertPos);

        //绘图结束的地方 = 当前位置+绘制去取的高度

        iPaintEnd = min(NUMLINES -1,iVertPos+ps.rcPaint.bottom/cyChar);



        for(i = iPaintBeg; i <= iPaintEnd;i++)

        {

            //绘图的x起始位置:1是自己设置的,设置越大离左边越宽

            x = cxChar * (1 - iHorzPos) ;

            //绘图的y起始位置。

            y = cyChar * (i - iVertPos) ;

            TextOut(hdc,x, y,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel));  

            //从22个大写字母以后的位置输出,因为第一列最多只有20个大写字母  

            TextOut(hdc,x+22*cxCaps,y,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szDesc));  

            SetTextAlign(hdc,TA_RIGHT | TA_TOP);

            TextOut(hdc,x+22*cxCaps+40*cxChar,y,szBuffer,wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics (sysmetrics[i].Index))); 

            SetTextAlign(hdc,TA_LEFT | TA_TOP);  

        }

        EndPaint (hwnd, &ps) ;

        return 0;

        

    //垂直滚动条消息

    case WM_VSCROLL:

        //获取垂直滚动条信息



        si.cbSize = sizeof(si);

        //所有参数

        si.fMask = SIF_ALL;

        GetScrollInfo(hwnd,SB_VERT,&si);

        //垂直位置

        iVertPos = si.nPos ;

        //通过滚动条消息的wParam表明滚动条的操作

        switch(LOWORD (wParam))

        {

        case SB_TOP:

            si.nPos = si.nMin;

            break;

        case SB_BOTTOM:

            si.nPos = si.nMax;

            break;

        case SB_LINEUP:

            si.nPos -= 1;

            break;

        case SB_LINEDOWN:

            si.nPos +=1;

        case SB_PAGEUP:

            si.nPage -= si.nPage;

            break;

        case SB_PAGEDOWN:

            si.nPos +=si.nPage;

            break;

        case SB_THUMBTRACK:

            si.nPos = si.nTrackPos;

            break;

        default:

            break;

        }

        



        si.fMask = SIF_POS;

        SetScrollInfo(hwnd,SB_VERT,&si,TRUE);

        GetScrollInfo(hwnd,SB_VERT,&si);

        if(si.nPos != iVertPos)

        {

            //滚动指定窗口的内容

            ScrollWindow(hwnd,0,cyChar*(iVertPos-si.nPos),NULL,NULL);

            UpdateWindow(hwnd);

        }

        return 0;

    //水平滚动条消息

    case WM_HSCROLL:

        si.cbSize = sizeof(si);

        si.fMask = SIF_ALL;

        GetScrollInfo(hwnd,SB_HORZ,&si);

        iHorzPos = si.nPos;

        switch(LOWORD(wParam))

        {

        case SB_LINELEFT:

            si.nPos -= 1;

            break;

        case SB_LINERIGHT:

            si.nPos +=1;

            break;

        case SB_PAGELEFT:

            si.nPos -= si.nPage;

            break;

        case SB_PAGERIGHT:

            si.nPos += si.nPage;

            break;

        case SB_THUMBPOSITION:

            si.nPos = si.nTrackPos;

            break;

        default:

            break;

            

        }

        si.fMask = SIF_POS;

        SetScrollInfo(hwnd,SB_HORZ,&si,TRUE);

        GetScrollInfo(hwnd,SB_HORZ,&si);

        if(si.nPos != iHorzPos)

        {

            ScrollWindow(hwnd,cxChar*(iHorzPos-si.nPos),0,NULL,NULL);

            //UpdateWindow (hwnd) ;



        }

        return 0;

    case  WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc (hwnd, message, wParam, lParam) ;



}

滑块大小的确定:

页面方块的大小/滚动的长度=页面大小/整个范围=显示文件的数量/整个文件的数量

程序中有几点需要注意:

1.程序中设置了垂直滚动条和水平滚动条。在WM_SIZE消息中,随着窗口的变化,滚动条的那个小方块的大小也在变化。

2.在每次使用GetScrollInfo或者SetScrollInfo之前,都必须有si.cbSize  = sizeof(si);这是因为兼容的缘故。而且还得指明操作的是SCROLLINFO中的哪些内容,这通过fMask来控制。

3.程序中有几行代码很费解:

iPaintBeg = max(0,iVertPos+ps.rcPaint.top/cyChar);实际上,由于ps.rcPaint.top=0,这行代码也可以写为:iPaintBeg = max(0,iVertPos);

iPaintEnd = min(NUMLINES -1,iVertPos+ps.rcPaint.bottom/cyChar);画图的结束位置=滚动条当前的位置+绘制的行数,而行数=客户区宽度/每一行的宽度;

x = cxChar * (1 - iHorzPos) ;绘图的x坐标,那个1是为了不是太“顶格”,你也可以把它设置大一点,结果就很明显了。

typedef struct tagSCROLLINFO

        

{

        

    UINT cbSize ;// set to sizeof (SCROLLINFO)

        

    UINT fMask ;  // values to set or get,要设置或获取的值

        

    int  nMin ;      // minimum range value,范围最小值

        

    int  nMax ;   // maximum range value,范围最大值

        

    UINT nPage ;  // page size,页面大小

        

    int  nPos ;   // current position,当前位置

        

    int  nTrackPos ;// current tracking position,当前追踪位置

        

}

        

SCROLLINFO, * PSCROLLINFO ;

ScrollWindow:

 函数原型:BOOL ScrollWindow(HWND hWnd, int XAmount, int YAmount, CONST RECT *IpRect, CONST RECT *lpClipRect);

参数:

hWnd
[in]客户区域将被滚动的窗口的句柄。
XAmount
[in]指定水平滚动的距离,以设备单位计。如果窗口类风格为CS_OWNDC或CS_CLASSDC,则此参数则使用逻辑单位而非设备单位。当向左滚动窗体内容时,参数值必须为负。
YAmount
[in]指定垂直滚动的距离,以设备单位计。如果窗口类风格为CS_OWNDC或CS_CLASSDC,则此参数则使用逻辑单位而非设备单位。当向上滚动窗体内容时,参数值必须为负。
lpRect
[in]指向RECT结构的指针,该结构指定了将要滚动的客户区范围。若此参数为NULL,则整个客户区域将被滚动。
lpClipRect
[in]指向RECT结构的指针,该结构指定了要滚动的裁剪区域。只有这个矩形中的位才会被滚动。在矩形之外的位不会被影响,即使它们是在lpRect矩形之内。(见代码"测试一")假如lpClipRect为NULL,则不会在滚动矩形上进行裁剪。
返回值:
如果函数运行成功,返回值为非零;如果函数运行失败,返回值为零。若想获得更多的错误信息,请调用GetLastReeor函数。
注意:
如果在被滚动的窗口中含有插入符, ScrollWindow将自动隐藏插入符,以防它被擦掉;当滚动结束后再恢复插入符。插入符的位置相应的被调整过来。
未被 ScrollWindow覆盖的区域不再重画,但该区域会与窗口更新区域组合。应用程序最终收到WM_PAINT的消息,通知它结合区域必须被重画。为了在滚动操作的同时重画未覆盖区域,则应在调用 ScrollWindow函数后马上调用 UpdateWindow函数。
如果参数lpRect为NULL,则窗口中的任何子窗口的位置由参数XAmount和Yamount的数值决定偏移;窗体无效(未着色)的区域也偏移。IpRect为NULL时ScrollWindow执行地更快。
如果参数lpRect不为NULL,则窗口中的子窗口的位置不改变,窗口中无效(未着色)的区域也不偏移。为了防止lpRect不为NULL时更新的问题,需要在调用 ScrollWindow前调用 UpdateWindow函数重绘窗口。
高效使用此函数的二法:

1.按照MSDN提供的方法来使用

调用完ScrollWindow后 ,立即调用UpdateWindow发送一个不进队的WM_PAINT消息。在WM_PAINT消息中可以按照滚动时的逻辑,整个区域都绘制但是利用重绘 区域自动将多余的绘制剪切掉,只绘制未被滚动操作覆盖的一行;但是更高明的做法无疑是只绘制未被滚动操作覆盖的一行,加快绘制速度。

2.在调用ScrollWindow的非WM_PAINT消息中绘制

在调用按ScrollWindow后获得窗口DC,自己绘制未被滚动操作覆盖的一行,然后将整个滚动剪切区域设为有效,禁止其产生WM_PAINT消息,这样也可加快绘制速度。

你可能感兴趣的:(windows)