码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-07-19 19:29:21      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:

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)); //变量名加个‘\0‘结束,所以iLength+1
            CopyMemory(pVarName, pVarBeg, iLength*sizeof(TCHAR));
            pVarName[iLength] = \0;    //变量名以‘\0‘结束
            //将变量名加入到列表框中,并释放内存
            SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)pVarName);
            free(pVarName);
        }
        while (*pVarCurr++ != \0); //找字符串的结束符‘\0‘,并把指针移向下一行开始。
    }
    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); //获得变量值的数据长度,含‘\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] = \0; //变成szBuffer变成[SubDir,加个\0
                if (!SetCurrentDirectory(szBuffer + 1))   //SubDir加上当前目录为新路径。失败,说明选中的是驱动器 
                {
                    szBuffer[3] = :; //变成[-c:]
                    szBuffer[4] = \0;//变成[-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);
}

 

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

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4658962.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!