Colors1程序

了解即可,不细细研究了

# include

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

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

//拥有输入焦点的滚动条的ID
int idFocus;

/*
可以查看一下定义:
ypedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
*/
WNDPROC OldScroll[3];//WNDPROC是函数指针

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    PSTR lpCmdLine,
    int iCmdShow
    )
{
    static TCHAR szAppName[] = TEXT("那又怎样");
    WNDCLASS wndclass;

    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hbrBackground = CreateSolidBrush(0);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//这里用NULL表示使用微软提供的图标
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //同上
    wndclass.hInstance = hInstance;
    wndclass.lpfnWndProc = WndProc;
    wndclass.lpszClassName = szAppName;
    wndclass.lpszMenuName = NULL;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClass(&wndclass))//注册窗口类
    {
        MessageBox(NULL, "Program requires windows NT!", szAppName, MB_ICONERROR);
        return 0;
    }

    HWND hwnd;
    hwnd = CreateWindow(szAppName,  TEXT("Color Scroll"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL, hInstance, NULL);//在窗口风格用或语句就可以加上滚动条了

    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,
    UINT uMsg,
    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 int color[3], cyChar;
    static RECT rcColor;
    static TCHAR *szColorLabel[] = { TEXT("Red"), TEXT("Green"), TEXT("Blue") };
    HINSTANCE hInstance;
    int i, cxClient, cyClient;
    TCHAR szBuffer[10];

    switch (uMsg)
    {
    case WM_CREATE:
        //获取WinMain里的hInstance
        hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);

        //Create the white-rectangle window against which the scroll bars will be positioned 
        //The child window ID is 9
        //左半部分背景
        hwndRect = CreateWindow(TEXT("static"), NULL, WS_CHILD | WS_VISIBLE| SS_GRAYRECT,
            0, 0, 0,0,
            hwnd, (HMENU)9, hInstance,NULL);


        for (i = 0; i < 3; i++)
        {
            //The three scroll bar have IDs 0,1 and 2,with scroll bar ranges from 0 through 255
            hwndScroll[i] = CreateWindow(TEXT("scrollbar"),  NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP
                | SBS_VERT,
                0, 0, 0, 0, hwnd, (HMENU)i, hInstance, NULL);
            /*    WS_TABSTOP
                  Specifies a control that can receive the keyboard focus when the user presses the TAB key. Pressing the TAB key changes the keyboard focus to the next control with the WS_TABSTOP style.
                  You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use SetWindowLong.
                  */
            SetScrollRange(hwndScroll[i], SB_CTL, 0, 255, FALSE);
            SetScrollPos(hwndScroll[i], SB_CTL, 0, FALSE);

            //The three color-name tables have IDs 3,4,and 5,and
            //text string "Red","Green",and "Blue".
            hwndLabel[i] = CreateWindow(TEXT("static"), szColorLabel[i], WS_CHILD | WS_VISIBLE | SS_CENTER,
                0, 0, 0, 0,
                hwnd,(HMENU)(i + 3), hInstance, NULL);

            //The three color-value text fields have IDs 6,7,and 8,
            //and initial text strints of "0".
            hwndValue[i] = CreateWindow(TEXT("static"),TEXT("0"), WS_CHILD | WS_VISIBLE | SS_CENTER,
                0, 0, 0, 0,
                hwnd, (HMENU)(i + 6), hInstance, NULL);

            //将三个滚动条的窗口过程设置为ScrollProc
            //试试三个滚动条的窗口过程都设置为同一窗口过程
            OldScroll[i] = (WNDPROC)SetWindowLong(hwndScroll[i], GWL_WNDPROC, (LONG)ScrollProc);
            hBrush[i] = CreateSolidBrush(crPrim[i]);
        }
        //用来画静态控件的画刷
        hBrushStatic = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));

        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 (i = 0; i < 3; i++)
        {
            MoveWindow(hwndScroll[i], (2 * i + 1)*cxClient / 14,2*cyChar, cxClient / 14, cyClient - 4 * cyChar, TRUE);
            MoveWindow(hwndLabel[i], (4 * i + 1)*cxClient / 28, cyChar / 2, cxClient / 7, cyChar, TRUE);
            MoveWindow(hwndValue[i], (4 * i + 1)*cxClient / 28, cyClient - 3 * cyChar / 2, cxClient / 7, cyChar, TRUE);
        }
        SetFocus(hwnd);
        return 0;

        //主窗口具有输入焦点时,使得id为idFocus的滚动条具有输入焦点
    case WM_SETFOCUS:
        SetFocus(hwndScroll[idFocus]);
        return 0;

    case WM_VSCROLL:
        //对于滚动条,lParam不会用到(为0),而对于滚动条控制其值为滚动条控制的窗口句柄
        i = GetWindowLong((HWND)lParam, GWL_ID);
        switch (LOWORD(wParam))
        {
        case SB_PAGEDOWN:
            color[i] += 15;
                    //fall through
        case SB_LINEDOWN:
            color[i] = min(255, color[i] + 1);
            break;

        case SB_PAGEUP:
            color[i] -= 15;

        case SB_LINEUP:
            color[i] = max(0, 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;

        default:
            break;
        }
        SetScrollPos(hwndScroll[i], SB_CTL, color[i], TRUE);
        wsprintf(szBuffer, TEXT("%d"), color[i]);
        SetWindowText(hwndValue[i], szBuffer);

        //删除未命名的背景画刷,即设计窗口类时用的:
        //wndclass.hbrBackground = CreateSolidBrush(0);
        //并用后面新创建的画刷代替
        DeleteObject((HBRUSH)SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(color[0], color[1], color[2]))));
        InvalidateRect(hwnd, &rcColor, TRUE);
        return 0;

        //查看msdn,一目了然
    case WM_CTLCOLORSCROLLBAR:
        i = GetWindowLong((HWND)lParam, GWL_ID);
        return (LRESULT)hBrush[i];

    case WM_CTLCOLORSTATIC:
        i = GetWindowLong((HWND)lParam, GWL_ID);

        if (i >= 3 && i <= 8)   //static text controls
        {
            SetTextColor((HDC)wParam, crPrim[i % 3]);
            SetBkColor((HDC)wParam,GetSysColor(COLOR_BTNHIGHLIGHT));
            return (LRESULT)hBrushStatic;//必须返回一个画刷用来画静态控件的背景
        }
        break;
        /*
        其实,i一定是在[3,8]范围,因为只有这6个控件是静态控件(创建窗口时包含SS_CENTER,为静态类型),所以
        父窗口只会收到这些控件的WM_CTLCOLORSTATIC消息,作者可能以为系统会收到别的控件的该消息,所以就break
        跳出这一循环,如果是return 0则不行
        */

    case WM_SYSCOLORCHANGE:
        DeleteObject(hBrushStatic);
        hBrushStatic = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
        return 0;

    case WM_CLOSE:
        auto iI = GCL_HBRBACKGROUND;
        //替换与类有关的背景刷子的句柄,这里就是删除注册窗口类时那个未命名的CreateSolidBrush(0)画刷句柄,并且
        //之后背景画刷为WHITE_BRUSH
        DeleteObject((HBRUSH)SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)GetStockObject(WHITE_BRUSH)));
        for (i = 0; i < 3; i++)
            DeleteObject(hBrush[i]);
        PostQuitMessage(0);
        //DestroyWindow(hwnd);
        return 0;
  }


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

}



LRESULT CALLBACK ScrollProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int id = GetWindowLong(hwnd, GWL_ID);

    switch (message)
    {
        //当前滚动条具有输入焦点,按下TAB键(同时按SHIFT键),GetKeyState(VK_SHIFT)<0,然后设置相应的滚动条
        //具有输入焦点
    case WM_KEYDOWN:
        if (wParam == VK_TAB)
            SetFocus(GetDlgItem(GetParent(hwnd), (id + (GetKeyState(VK_SHIFT) < 0 ? 2 : 1)) % 3));
        break;//不要return 0;外层还有主窗口的循环

    case WM_SETFOCUS:
        idFocus = id;//具有输入焦点时更新idFocus的值
        break;
    default:
        break;
    }
    /*可以使用带GWL_WNDPROC索引值的SetWindowLong函数创建一个窗口类的子类,该窗口类是用于创建该窗口的类。
    一个应用程序可以以一个系统类为子类,但是不能以一个其他进程产生的窗口类为子类,SetwindowLong函数通过
    改变与一个特殊的窗口类相联系的窗口过程来创建窗口子类,从而使系统调用新的窗口过程而不是以前定义的窗口过程。
    应用程序必须通过调用CallWindowProc函数向前窗口传递未被新窗口处理的消息,这样作允许应用程序创建一个窗口
    过程链。
    */
        return CallWindowProc(OldScroll[id], hwnd,message, wParam,lParam);
}

Colors1程序_第1张图片

你可能感兴趣的:(windows程序设计之旅)