• 第9章 子窗口控件_9.4-9.6滚动条类、编辑框类、列表框类


    9.4 滚动条类

    9.4.1 滚动条控件

    (1)窗口滚动条与滚动条控件的比较

     

    窗口滚动条

    滚动条控件

    消息

    发送WM_VSCROLL、WM_HSCROLL消息。不发送WM_COMMAND消息。wParam参数的意义是一样的。lParam:当消息来自窗口滚动条时为NULL,来自滚动条控件时为滚动条的句柄。

    宽度或高度

    固定大小

    //水平滚动条高度

    GetSysMetrics(SM_CYHSCROLL);

    //垂直滚动条宽度

    GetSysMetrics(SM_CYVSCROLL)

    1、大小、位置均可设定;

    2、在CreateWindow或MoveWindow函数中指定,大小可自定义。

    窗口样式

    WS_VSCROLL:垂直滚动条(在窗口右侧)

    WS_HSCROLL:水平滚动条(在窗口下方)

    可用滚动条样式和尺寸

    SBS_VERT、SBS_HORZ、

    S SBS_TOPALIGN、  BS_BOTTOMALIGN、SBS_LEFTALIGN、SBS_RIGHTALIGN等。

    调用函数

    的参数

    SetScrollInfo(hwnd,SB_VERT,

    &si,bRedraw);

    SetScrollInfo(hwndScroll,SB_CTL,

    &si,bRedraw);

    (2)滚动条的颜色

    ①滚动条两端的按钮及滑块:COLOR_BTNFACE、COLOR_BTNHILIGHT、COLOR_BTNSHADOW、COLOR_BTNTEXT(给小箭头用)、COLOR_DKSHADOW及COLOR_BTNLIGHT

    ②两端按钮之间的大片区域:COLOR_BTNFACE、COLOR_BTNHIGHLIGHT的某种组合。

    9.4.2 COLORS1程序

    (1)窗口子类化

    ①用自定义窗口过程(ScrollProc)替换Windows的内部窗口过程

       OldScroll[i]=(WNDPROC)SetWindowLong(hwndScroll[i], GWL_WNDPROC, (LONG)ScrollProc);

    ②调用旧的滚动条窗口过程

    CallWindowProc(OldScroll[id],hwnd, message, wParam, lParam);

    (2)主窗口背景着色

          ①准备好背景画刷:新建画刷→存入窗口类结构→删除旧画刷

             DeleteObject((HBRUSH)

                   SetClassLong(hwnd, GCL_HBRBACKGROUND,(LONG)

                           CreateSolidBrush(RGB(color[0],color[1], color[2]))));

    ②终止程序时清除画刷

       DeleteObject((HBRUSH)

            SetClassLong(hwnd, GCL_HBRBACKGROUND,(LONG)GetStockObject(WHITE_BRUSH)));

    (3)滚动条和静态文本着色

        ①3个滚动条背景色:hBrush[i] = CreateSolidBrush(crPrim[i]);

        ②在WM_CTLCOLORSCROLLBAR中return (LRESULT)hBrush[i],返回画刷,即可着色。

        ③静态文本在WM_CTLCOLORSTATIC中通过SetBkColor和SetTextColor为文本着色。

    【Color1程序】

    /*------------------------------------------------------------
    COLORS1.C -- Colors Using Scroll Bars
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT ScrollProc(HWND, UINT, WPARAM, LPARAM);
    int idFocus; //当前选中的滚动条
    WNDPROC OldScroll[3]; //原3个滚动条控件的窗口过程
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("Colors1");
        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))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
            TEXT("Color Scroll1"), // window caption
            WS_OVERLAPPEDWINDOW,        // window style
            CW_USEDEFAULT,              // initial x position
            CW_USEDEFAULT,              // initial y position
            CW_USEDEFAULT,              // initial x size
            CW_USEDEFAULT,              // initial y size
            NULL,                       // parent window handle
            NULL,                       // window menu handle
            hInstance,                  // program instance handle
            NULL);                     // creation parameters
    
        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 COLORREF crPrim[3] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255) };
        static HBRUSH hBrush[3], hBrushStatic;//三个滚动条的背景画刷
        static HWND hwndScroll[3], hwndLabel[3], hwndValue[3], hwndRect;
        static TCHAR* szColorLabel[] = { TEXT("Red"), TEXT("Green"), TEXT("Blue") };
        TCHAR szBuffer[10];
        static int cxChar, cyChar;
        HINSTANCE hInstance;
        static RECT     rcColor;
        static int color[3]; //三个滚动条当前的颜色值
        int i, cxClient, cyClient;
        switch (message)
        {
        case WM_CREATE:
            //hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
            hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
            //创建一个白色矩形区,用来放置控件,窗口ID为9.
            hwndRect = CreateWindow(TEXT("static"),
                NULL,
                WS_CHILD | WS_VISIBLE | SS_WHITERECT,
                0, 0, 0, 0,
                hwnd,
                (HMENU)9, hInstance, NULL);
            for (int i = 0; i< 3; i++)
            {
                //创建三个滚动条,范围0-255,ID分别为0,1.2
                hwndScroll[i] = CreateWindow(TEXT("scrollbar"), NULL,
                    WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_VERT, //垂直,可接受Tab键
                    0, 0, 0, 0,
                    hwnd,
                    (HMENU)i, hInstance, NULL);
                SetScrollRange(hwndScroll[i], SB_CTL, 0, 255, FALSE);
                SetScrollPos(hwndScroll[i], SB_CTL, 0, FALSE);
                //3个颜色名称为"Red"、"Green"、"Blue"的标签,ID分别为3,4,5
                hwndLabel[i] = CreateWindow(TEXT("static"),
                    szColorLabel[i],
                    WS_CHILD | WS_VISIBLE | SS_CENTER,
                    0, 0, 0, 0,
                    hwnd,
                    (HMENU)(i + 3), hInstance, NULL);
                //3种颜色值的标签,ID分别为6,7,8
                hwndValue[i] = CreateWindow(TEXT("static"),
                    TEXT("0"),
                    WS_CHILD | WS_VISIBLE | SS_CENTER,
                    0, 0, 0, 0,
                    hwnd,
                    (HMENU)(i + 6), hInstance, NULL);
    
                //3个滚动条的背景画刷
                hBrush[i] = CreateSolidBrush(crPrim[i]);
                OldScroll[i] = (WNDPROC)SetWindowLong(hwndScroll[i], GWL_WNDPROC, (LONG)ScrollProc);
            }
            hBrushStatic = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
            cxChar = LOWORD(GetDialogBaseUnits());
            cyChar = HIWORD(GetDialogBaseUnits());
            return 0;
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            SetRect(&rcColor, cxClient / 2, 0, cxClient, cyClient);
            MoveWindow(hwndRect, 0, 0, cxClient / 2, cyClient, TRUE);
            for (int i = 0; i < 3; i++)
            {
                //设置滚动条在主窗口大小和位置:宽cxClient/14,高cyClient -4*cyChar;
                MoveWindow(hwndScroll[i], (2 * i + 1)*cxClient / 14, 2 * cyChar, cxClient / 14, cyClient - 4 * cyChar, TRUE);
                MoveWindow(hwndLabel[i], (2 * i + 1)*cxClient / 14, cyChar / 2, cxClient / 14, cyChar, TRUE);
                MoveWindow(hwndValue[i], (2 * i + 1)*cxClient / 14, cyClient - 3 * cyChar / 2, cxClient / 14, cyChar, TRUE);
            }
            SetFocus(hwnd);
            return 0;
        case WM_VSCROLL:
            //获取子窗口ID
            i = GetWindowLong((HWND)lParam, GWL_ID);
            switch (LOWORD(wParam))
            {
            case SB_PAGEDOWN: //每次增长16;
                color[i] += 16;
                break;
            case SB_PAGEUP:
                color[i] -= 16;
                break;
            case SB_LINEDOWN:
                color[i] += 1;
                break;
            case SB_LINEUP:
                color[i] -= 1;
                break;
            case SB_TOP:
                color[i] = 0;
                break;
            case SB_BOTTOM:
                color[i] = 255;
                break;
            case SB_THUMBPOSITION:
            case SB_THUMBTRACK:
                color[i] = HIWORD(wParam);
                break;
            }
            color[i] = max(0, min(255, color[i]));
    
            SetScrollPos(hwndScroll[i], SB_CTL, color[i], TRUE);
            wsprintf(szBuffer, TEXT("%i"), color[i]); //%i与%d相同
            SetWindowText(hwndValue[i], szBuffer);
            //设置窗口类的背景颜色
            DeleteObject((HBRUSH)
                SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)
                CreateSolidBrush(RGB(color[0], color[1], color[2]))));
    
            InvalidateRect(hwnd, &rcColor, TRUE);
            return 0;
        case WM_CTLCOLORSCROLLBAR: //wParam:DC,lParam:滚动条句柄
            i = GetWindowLong((HWND)lParam, GWL_ID);
            return (LRESULT)hBrush[i]; //须返回画刷句柄
        case WM_CTLCOLORSTATIC://wParam:DC,lParam:静态类文本的句柄
            i = GetWindowLong((HWND)lParam, GWL_ID);
            if (i >= 3 && i <= 8)
            {
                SetBkColor((HDC)wParam, GetSysColor(COLOR_BTNHIGHLIGHT));
                SetTextColor((HDC)wParam, crPrim[i % 3]);
                return (LRESULT)hBrushStatic;
            }
            break;
        case WM_SYSCOLORCHANGE:
            DeleteObject(hBrushStatic);
            hBrushStatic = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
            return 0;
        case WM_SETFOCUS:
            SetFocus(hwndScroll[idFocus]);
            return 0;
    
        case WM_DESTROY:
            //将主窗口画刷设为白色
            DeleteObject((HBRUSH)
                SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(WHITE_BRUSH)));
            DeleteObject(hBrushStatic);
            for (int i = 0; i < 3; i++)
                DeleteObject(hBrush[i]);
    
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    //窗口子类化
    LRESULT ScrollProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int id = GetWindowLong(hwnd, GWL_ID);//获子窗口ID
        switch (message)
        {
        case WM_KEYDOWN:
            if (wParam == VK_TAB)
            {
                SetFocus(GetDlgItem(GetParent(hwnd), (id + 1) % 3));
            }
            break;
        case WM_SETFOCUS:
            idFocus = id;
            break;
        }
        //调用子窗口旧的窗口过程
        return CallWindowProc(OldScroll[id], hwnd, message, wParam, lParam);
    }
    9.5 编辑类

    9.5.1 编辑类的样式

    样式

    说明

    ES_LEFT

    文本对齐方式

    ES_RIGHT

    ES_CENTER

    ES_MULTILINE

    多行编辑控件

    ES_AUTOHSCROLL

    默认会自动文本,加这后不会自动换行,要按回车键。

    ES_AUTOVSCROLL

    垂直滚动条

    ES_NOHIDESEL

    失去焦,选中时仍高亮显示

    9.5.2 编辑控件的通知消息:WM_COMMAND

    参数

    含义

    lParam

    子窗口句柄

    wParam

    LOWORD(wParam):子窗口ID

    HIWORD(wParam):通知码

    EN_SETFOCUS:得到焦点

    EN_KILLFOCUS:失去焦点

    EN_CHANGE:   内容改变

    EN_UPDATE:   内容己变化

    EN_ERRSPACE: 没有空间了

    EN_MAXTEXT:  输入超过最大长度

    EN_HSCROLL:  水平滚动条被单击

    EN_VSCROLL:  垂直滚动条被单击

    9.5.3 使用编辑控件

      ①SetWindowText:输入文本

      ②GetWindowText:读取文本

      ③GetWindowTextLength:获得文本长度

    9.5.4 传递消息给编辑控件

    操作

    消息

    复制、剪切、

    清除、粘贴

    SendMessage(hwndEdit,WM_COPY,0,0);

    SendMessage(hwndEdit,WM_CUT,0,0);

    SendMessage(hwndEdit,WM_CLEAR,0,0);

    SendMessage(hwndEdit,WM_PASTE,0,0);

    获取选择文本的位置

    SendMessage(hwndEdit,EM_GETSEL,(WPARAM&iStart,(LPARAM)&iEND);

    选择文本

    SendMessage(hwndEdit,EM_SETSEL,iStart,iEnd);

    获得行数

    iCount = SendMessage(hwndEdit,EM_LINECOUNT,0,0);

    编辑缓冲区起点到指定行的位移量

    iOffset = SendMessage(hwndEdit,EM_LINELENGTH,iLine,0);

    //如果iLine =-1,则返回插入符号所在行的位移量。

    获到某行的长度

    iLength = SendMessage(hwndEdit,EM_LINELENGTH,iLine,0);

    复制一行到缓冲区

    iLength = SendMessage(hwndEdit,EM_GETLINE,iLine,(LPARAM)szBuffer

    【PopPad1程序】

    /*------------------------------------------------------------
    POPPAD1.C -- Popup Editor using child window edit box
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    #define ID_EDIT 1
    static TCHAR szAppName[] = TEXT("PopPad1");
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        PSTR szCmdLine, int iCmdShow)
    {
    
        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))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
            TEXT("edit"), // window caption
            WS_OVERLAPPEDWINDOW,        // window style
            CW_USEDEFAULT,              // initial x position
            CW_USEDEFAULT,              // initial y position
            CW_USEDEFAULT,              // initial x size
            CW_USEDEFAULT,              // initial y size
            NULL,                       // parent window handle
            NULL,                       // window menu handle
            hInstance,                  // program instance handle
            NULL);                     // creation parameters
    
        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 HWND hwndEdit;
    
        switch (message)
        {
        case WM_CREATE:
            hwndEdit = CreateWindow(TEXT("edit"), NULL,
                WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
                WS_BORDER | ES_LEFT | ES_MULTILINE |
                ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,
                ((LPCREATESTRUCT)lParam)->hInstance, NULL);
            return 0;
        case WM_SETFOCUS:
            SetFocus(hwndEdit);
            return 0;
        case WM_COMMAND:
            if (LOWORD(wParam) == ID_EDIT)
            {
                if (HIWORD(wParam) == EN_ERRSPACE ||
                    HIWORD(wParam) == EN_MAXTEXT)
                {
                    MessageBox(hwnd, TEXT("Edit Control out of space."),
                        szAppName, MB_OK | MB_ICONSTOP);
                }
            }
            return 0;
        case WM_SIZE:
            MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    9.6 列表框类

    键盘操作

    单选列表框

    多选列表框

    空格键

    选择光标所在项

    切换选中状态

    方向键

    移动光标和当前的选择

    取消以前所选,并移动光标和选中项

    翻页键

    移动光标,但不移动选择项

    字母键

    移动和选择以该字母开头的第一项

    Ctrl+方向

    移动光标,但不移动选中项

    Shift+方向

    扩展选中项

    9.6.1 列表框的样式

    样式

    含义

    LBS_NOTIFY

    默认的列表框样式不能发送WM_COMMAND到父窗口,须指定该样式才行

    LBS_SORT

    排序

    LBS_MULTIPLESEL

    多选

    LBS_NOREDRAW

    新增项目默认不会自我更新,可在WM_SETREDRAW中设置

    LBS_STANDARD

    标准列表框:LBS_NOTIFY|LBS_SORT|WS_VSCROLL|WS_BORDER

     ★设定列表框的宽度:最长字符串长度+滚动条的宽度

     ★设定列表框的高度:1个字符的高度*视图中项目的数量

    9.6.2 向列表框中添加字符串

    操作

    SendMessage:

    返回值——LB_ERRSPACE或LB_ERR或LB_OKAY

    在列表框最后增加一项

    (hwndList,LB_ADDSTRING,0,(LPARAM)szString);

    //如果LBS_SORT则会插到顺序后相应的位置。

    插入到指定位置

     hwndList,LB_INSERTSTRING,iIndex,(LPARAM)szString)

    //当iIndex=-1时,会被添加到最底部。

    删除索引位置处的一个字符串

    (hwndList,LB_DELETESTRING,iIndex,0);

    清除所有项目

    (hwndList,LB_RESETCONTENT,iIndex,0);

    开关控件重绘标志

    (hwndList,WM_SETREDRAW,FALSE,0);

    (hwndList,WM_SETREDRAW,TRUE,0);

    9.6.3 项目的选择和提取

    (1)获取列表框项目数量:iCount=SendMessage(hwndList,LB_GETCOUNT,0,0)

    (1)单选列表框

    单选列表框操作

    相应代码

    突出选择某项

    SendMessage(hwndList,LB_SETCURSEL,iIndex,0);

    //lParam为-1时,取消选中所有项

    根据起始字符选择一项

    SendMessage(hwndList,LB_SELECTSTRING,iIndex,

    (LPARAM)szSerchString);

    //如果参数iIndex=-1,那么从顶端开始查找。

    //返回值:被选中的索引或没有匹配时为LB_ERR

    获取当前选中项的索引

    iIndex = SendMessage(hwndList,LB_GETCURSEL,0,0)

    获取某项字符串长度

    iLength = SendMessage(hwndList,LB_GETTEXTLEN,iIndex,0)

    读取项目到缓冲区

    iLength =SendMessage(hwndList,LB_GETTEXT,iIndex,

    (LPARAM)szBuffer);

    (3)多选列表框(不能使用LB_SETCURSEL,LB_GETCURSEL或LB_SELECTSTRING)

    操作

    相应代码

    设置某项选择状态

    (不影响其他项)

    SendMessage(hwndList,LB_SETSEL,wParam,iIndex);

    //wParam非零时,选中并高亮该项,为0时取消选择

    //lParam是-1时,在选择和取消所有项之间切换

    检查选择状态

    iSelect = SendMessage(hwndList,LB_GETSEL,iIndex,0);

    //iSelect非零,表示选中。为零时,未选中

    9.6.4 接收来自列表框的消息

    参数

    含义

    lParam

    子窗口句柄

    wParam

    LOWORD(wParam):子窗口ID

    HIWORD(wParam):通知码

    LBN_ERRSPACE: 空间不够

    LBN_SELCHANGE:当前选择发生变化

    LBN_DBLCLK:   双击

    LBN_SELCANCEL:取消选择

    LBN_SETFOCUS: 得到焦点

    LBN_KILLFOCUS:失去焦点

    【ENVIRON.C程序】

    (1)环境变量格式

    (2)获取和释放环境变量块GetEnvironmentStrings、FreeEnvironmentStrings
    (3)获取环境变量 GetEnvironmentVariable
    效果图:

     

    /*------------------------------------------------------------
    ENVIRON.C -- Environment List Box
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    #define ID_LIST 1
    #define ID_TEXT 2
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("Environ");
        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)(COLOR_WINDOW + 1);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
            TEXT("Environment List Box"), // window caption
            WS_OVERLAPPEDWINDOW,        // window style
            CW_USEDEFAULT,              // initial x position
            CW_USEDEFAULT,              // initial y position
            CW_USEDEFAULT,              // initial x size
            CW_USEDEFAULT,              // initial y size
            NULL,                       // parent window handle
            NULL,                       // window menu handle
            hInstance,                  // program instance handle
            NULL);                     // creation parameters
    
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    void FillListBox(HWND hwndList)
    {
        TCHAR *pVarBlock, *pVarCurr, *pVarBeg, *pVarEnd, *pVarName;
        int iLength;
        //获得环境变量的指针
        pVarCurr = pVarBlock = GetEnvironmentStrings();
        while (*pVarCurr)
        {
            if (*pVarCurr != '=')           //跳过无意义的“=::=::”或"=E:=E:ABC"格式的字符串
            {
                pVarBeg = pVarCurr;            //变量名的开始位置。注意环境变量的格式varName=value
                while (*pVarCurr++ != '=');    //扫描到‘=’号
                pVarEnd = pVarCurr - 1;        //pVarCurr指向'='号
    
                iLength = pVarEnd - pVarBeg;   //变量名的长度
                //分配内存给变量名
                pVarName = calloc(iLength + 1, sizeof(TCHAR)); //变量名加个''结束,所以iLength+1
                CopyMemory(pVarName, pVarBeg, iLength*sizeof(TCHAR));
                pVarName[iLength] = '';    //变量名以''结束
                //将变量名加入到列表框中,并释放内存
                SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)pVarName);
                free(pVarName);
            }
            while (*pVarCurr++ != ''); //找字符串的结束符'',并把指针移向下一行开始。
        }
        FreeEnvironmentStrings(pVarBlock);
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HWND hwndList, hwndText;
        int cxChar, cyChar;
        int iLength, iIndex;
        TCHAR *pVarName, *pVarValue;
        switch (message)
        {
        case WM_CREATE:
            cxChar = LOWORD(GetDialogBaseUnits());
            cyChar = HIWORD(GetDialogBaseUnits());
    
            //创建列表框
            hwndList = CreateWindow(TEXT("listbox"), NULL,
                WS_CHILD | WS_VISIBLE | LBS_STANDARD,
                cxChar, cyChar * 3,
                cxChar * 35 + GetSystemMetrics(SM_CXVSCROLL),
                cyChar * 15,
                hwnd, (HMENU)ID_LIST,
                (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
    
            hwndText = CreateWindow(TEXT("static"), NULL,
                WS_CHILD | WS_VISIBLE | SS_LEFT,
                cxChar, cyChar,
                GetSystemMetrics(SM_CXSCREEN),
                cyChar,
                hwnd, (HMENU)ID_TEXT,
                (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
    
            FillListBox(hwndList);
            return 0;
        case WM_COMMAND:
            if (LOWORD(wParam) == ID_LIST &&HIWORD(wParam) == LBN_SELCHANGE)
            {
                //获取列表框的中变量名称
                iIndex = SendMessage(hwndList, LB_GETCURSEL, 0, 0);     //获得当前选中项索引
                iLength = SendMessage(hwndList, LB_GETTEXTLEN, iIndex, 0) + 1;//获得文本长度
                pVarName = calloc(iLength, sizeof(TCHAR)); //calloc初始化元素为0
                SendMessage(hwndList, LB_GETTEXT, iIndex, (LPARAM)pVarName); //获取变量名称
                //获取环境变量名称
                iLength = GetEnvironmentVariable(pVarName, NULL, 0); //获得变量值的数据长度,含''
                pVarValue = calloc(iLength, sizeof(TCHAR));
                GetEnvironmentVariable(pVarName, pVarValue, iLength);//获得变量的值
                //将变量的值显示在文本框中
                SetWindowText(hwndText, pVarValue);
                free(pVarValue);
                free(pVarName);
            }
            return 0;
        case WM_SETFOCUS:
            SetFocus(hwndList);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
     9.6.5 列出文件:SendMessage(hwndList,LB_DIR,iAttr,(LPARAM)szFileSpec);

    (1)文件属性代码iAttr——下列数值的组合的(最后两个位于高字节)

     iAttr

    属性

    DDL_READWRITE (0x0000)

    普通文件

    DDL_READONLY  (0x0001)

    只读文件

    DDL_HIDDEN    (0x0002)

    隐藏文件

    DDL_SYSTEM    (0x0004)

    系统文件

    DDL_DIRECTORY (0x0010)

    子目录

    DDL_ARCHIVE   (0x0020)

    设置了存档位的文件

    DDL_DRIVES    (0x4000)

    包括驱动器字符,如形如“[-C-]”

    DDL_EXCLUSIVE (0x8000)

    只搜索指定值

           ①前缀DDL:Dialog directory list(对话框目录列表)

           ②如果最高位被设置,则只列出具有某种标志的文件:

    如只列出自上次备份以来所有被修改过的文件——DDL_EXCLUSIVE|DDL_ARCHIVE

    (2)文件列表的排序:(要使用LBS_SORT样式)

    文件列表排序

    说明

    ①先列出满足文件限定条件的所有文件名称

     

    ②再列子目录名称

    A、第一个子目录[..]:用于返回上一级目录,如果己经是根目录没有这东西。

    B、其他子目录[SUBDIR]

    C、该项是可选的

    ③最后磁盘驱动器清单

    A、驱动器清单,形如:[-A-]

    B、该项也是可选的

     9.6.6 Windows的HEAD程序

    (1)窗口子类化

       在ListProc中捕捉WM_KEYDOWN消息,发现VK_RETURN则发送WM_COMMAND(带LBN_DBLCKL)通知码的消息给父窗口。

    (2)获取当前目录或设置当前目录

       GetCurrentDirectory(MAX_PATH + 1, szBuffer);//当前目录

       SetCurrentDirectory(szBuffer);//将当前目录设置为指定的目录

    (3)打开文件和关闭文件:

    打开文件:HANDLE hFile =CreateFile(…);

    读取文件:ReadFile(hFile, buffer, nNumberOfBytesToRead, lpNumberOfBytesRead,NULL);

    关闭文件:CloseFile(hFile);

    效果图

     

    /*------------------------------------------------------------
    HEAD.C -- Displays beginning (head) of file
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    #define ID_LIST 1
    #define ID_TEXT 2
    #define MAXREAD 8192
    #define DIRATTR  (DDL_READWRITE|DDL_READONLY|DDL_HIDDEN|DDL_SYSTEM|
        DDL_DIRECTORY | DDL_ARCHIVE | DDL_DRIVES)
    #define DTFLAG (DT_WORDBREAK|DT_EXPANDTABS|DT_NOCLIP|DT_NOPREFIX)
    WNDPROC OldList;
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK ListProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("head");
        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)(COLOR_BTNFACE + 1);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
            TEXT("head"), // window caption
            WS_OVERLAPPEDWINDOW,        // window style
            CW_USEDEFAULT,              // initial x position
            CW_USEDEFAULT,              // initial y position
            CW_USEDEFAULT,              // initial x size
            CW_USEDEFAULT,              // initial y size
            NULL,                       // parent window handle
            NULL,                       // window menu handle
            hInstance,                  // program instance handle
            NULL);                     // creation parameters
    
        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)
    {
        HDC         hdc;
        PAINTSTRUCT ps;
        static RECT rect; //在客户区指定的地方显示文件的内容
        int i, cxChar, cyChar;
        static HWND hwndList, hwndText;
        static TCHAR szFile[MAX_PATH + 1]; //保存选中的文件名
        TCHAR szBuffer[MAX_PATH + 1];
        static BYTE buffer[MAXREAD];
        static BOOL bValidFile;
        HANDLE hFile;
        switch (message)
        {
        case WM_CREATE:
            cxChar = LOWORD(GetDialogBaseUnits());
            cyChar = HIWORD(GetDialogBaseUnits());
            rect.top = 3 * cyChar;
            rect.left = 25 * cxChar;
            hwndList = CreateWindow(TEXT("listbox"), NULL,
                WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD,
                cxChar, 3 * cyChar,
                cxChar * 20 + GetSystemMetrics(SM_CXVSCROLL),
                cyChar * 20,
                hwnd,
                (HMENU)ID_LIST,
                (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                NULL
                );
            GetCurrentDirectory(MAX_PATH + 1, szBuffer); //当前目录
            hwndText = CreateWindow(TEXT("static"), szBuffer,
                WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
                cxChar, cyChar, cxChar * MAX_PATH, cyChar,
                hwnd,
                (HMENU)ID_TEXT,
                (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                NULL
                );
            OldList = (WNDPROC)SetWindowLong(hwndList, GWL_WNDPROC, (LONG)ListProc);
            SendMessage(hwndList, LB_DIR, DIRATTR, (LPARAM)TEXT("*.*"));
            return 0;
        case WM_SIZE:
            rect.right = LOWORD(lParam);
            rect.bottom = HIWORD(lParam);
            return 0;
        case WM_SETFOCUS:
            SetFocus(hwndList);
            return 0;
        case WM_COMMAND:
            if (LOWORD(wParam) == ID_LIST && HIWORD(wParam) == LBN_DBLCLK)
            {
                //判断是否选中项目
                if (LB_ERR == (i = SendMessage(hwndList, LB_GETCURSEL, 0, 0)))
                    break;
                //获取选中项的文本
                SendMessage(hwndList, LB_GETTEXT, i, (LPARAM)szBuffer);
                //打开文件
                hFile = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
                if (INVALID_HANDLE_VALUE != hFile)   //选中项为文件
                {
                    CloseHandle(hFile);
                    bValidFile = TRUE;
                    lstrcpy(szFile, szBuffer); //保存选中项的文件名
                    //将文件及路径显示在文本框中
                    GetCurrentDirectory(MAX_PATH + 1, szBuffer);
                    if (szBuffer[lstrlen(szBuffer) - 1] != '\')
                    {
                        lstrcat(szBuffer, TEXT("\"));  //最未尾加个“”
                    }
                    SetWindowText(hwndText, lstrcat(szBuffer, szFile));
                }
                else
                {
                    //选中项为目录或驱动器
                    //1、上级目录:[..]
                    //2、子目录如:[SubDir]
                    //3、驱动器符:[-c-]
                    bValidFile = FALSE;
                    //判断是否目录
                    szBuffer[lstrlen(szBuffer) - 1] = ''; //变成szBuffer变成[SubDir,加个
                    if (!SetCurrentDirectory(szBuffer + 1))   //SubDir加上当前目录为新路径。失败,说明选中的是驱动器 
                    {
                        szBuffer[3] = ':'; //变成[-c:]
                        szBuffer[4] = '';//变成[-c:
                        SetCurrentDirectory(szBuffer + 2); //将当前路径设为驱动器符,如c:
                    }
                    //转到子目录或选中的驱动器的根目录下,获取当前路径。
                    GetCurrentDirectory(MAX_PATH + 1, szBuffer);
                    //显示当前路径
                    SetWindowText(hwndText, szBuffer);
                    //清空列表框
                    SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
                    //显示当前目录下的文件及子目录等信息
                    SendMessage(hwndList, LB_DIR, DIRATTR, (LPARAM)TEXT("*.*"));
                }
    
                InvalidateRect(hwnd, NULL, TRUE);
            }
            return 0;
        case WM_PAINT:
            if (!bValidFile) break; //这里不做任何事,交给DefWindowProc处理
            //打开文件
            hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
            if (INVALID_HANDLE_VALUE == hFile)   //打开文件失败
            {
                bValidFile = FALSE;
                break;
            }
            //读取文件内容
            ReadFile(hFile, buffer, MAXREAD, &i, NULL);
            CloseHandle(hFile);
            //显示读取到的内容,i为读取文本到buffer中的字节总数
            hdc = BeginPaint(hwnd, &ps);
            SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
            SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
            SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
            //假定是ASCII字符的文件
            DrawTextA(hdc, buffer, i, &rect, DTFLAG);
    
            EndPaint(hwnd, &ps);
            return 0;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    LRESULT CALLBACK ListProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        if (message == WM_KEYDOWN && wParam == VK_RETURN)
        {
            SendMessage(GetParent(hwnd), WM_COMMAND, MAKELONG(ID_LIST, LBN_DBLCLK), (LPARAM)hwnd);
        }
        return CallWindowProc(OldList, hwnd, message, wParam, lParam);
    }
  • 相关阅读:
    开源交易所源码搜集
    域名
    国外大牛博客
    Fomo3D代码分析以及漏洞攻击演示
    Small组件化重构安卓项目
    html span和div的区别
    七牛云
    以太坊钱包安全性保证
    跨域问题
    checkout 到bit/master分支
  • 原文地址:https://www.cnblogs.com/5iedu/p/4658962.html
Copyright © 2020-2023  润新知