抖音熱門數(shù)字時鐘設(shè)計

win32GDI項目數(shù)字時鐘

前言:基于win32GDI繪圖制作抖音熱門數(shù)字時鐘

定時器

開啟定時器
//定義定時器ID
#define IDT_TIME 1001
//設(shè)置定時器
SetTimer(hWnd
         , IDT_TIME //定時器ID
         , 1000     //定時間隔 單位毫秒ms
         , NULL);   //參數(shù)為NULL時以政,定時向程序投遞WM_TIMER消息
匹配定時器消息
    case WM_TIMER:
        switch (wParam)
        {
            case IDT_TIME:
                {
                    HDC hdc = GetDC(hWnd);
                    static int y = 0;
                    TextOut(hdc, 0, y += 20, L"定時器開啟第",6);
                    ReleaseDC(hWnd, hdc);
                }
                break;
            default:
                break;
        }
        break;
關(guān)閉定時器
KillTimer(hWnd, IDT_TIME);

系統(tǒng)時間

系統(tǒng)時間結(jié)構(gòu)體 SYSTEMTIME

獲取系統(tǒng)時間
    wchar_t szTime[100];
    SYSTEMTIME currentTime;
    
    GetLocalTime(&currentTime);
            wsprintf(szTime, L"%.2d %.2d %.2d %.2d:%.2d:%.2d\n", currentTime.wYear,
                currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond);
            TextOut(hdc, 0, 0, szTime, wcslen(szTime) - 1);

定時器+時鐘 = 簡陋的數(shù)字時鐘

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    wchar_t szTime[100];
    SYSTEMTIME currentTime;
    switch (message)
    {
    case WM_CREATE:
        SetTimer(hWnd, IDT_TIME, 1000, NULL);
        break;
    case WM_RBUTTONDOWN:
        KillTimer(hWnd, IDT_TIME);
        break;
    case WM_TIMER:
        switch (wParam)
        {
        case IDT_TIME:
        {
            HDC hdc = GetDC(hWnd);
            GetLocalTime(&currentTime);
            wsprintf(szTime, L"%.2d %.2d %.2d %.2d:%.2d:%.2d\n", currentTime.wYear,
                currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond);
            TextOut(hdc, 0, 0, szTime, wcslen(szTime) - 1);
            ReleaseDC(hWnd, hdc);
        }
            break;
        default:
            break;
        }
        break;
    case WM_COMMAND:
        break;
    case WM_PAINT:
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

效果顯示

去標題欄

創(chuàng)建窗口的時候自定義窗口風格

    // 創(chuàng)建主窗口
    HWND hwnd = CreateWindowEx(
        0,          // dwExStyle,擴展樣式   
        szClassName,        // lpClassName级零,類名           
        L"時鐘",  // lpWindowName横浑,標題      
        WS_POPUP|WS_SYSMENU|WS_SIZEBOX, // dwStyle,窗口風格 WS_POPUP|WS_SYSMENU去標題欄所需宏
        100,        // X,初始 X 坐標        
        100,        // Y邦危,初始 Y 坐標        
        300,        // nWidth,寬度            
        300,        // nHeight舍扰,高度           
        NULL,           // hWndParent倦蚪,父窗口句柄         
        NULL,           // hMenu,菜單句柄       
        hInstance,      // hlnstance边苹,程序?qū)嵗浔?    
        NULL);          // lpParam审丘,用戶數(shù)據(jù)     

移動窗口

截取DefWindowProc消息

    case WM_NCHITTEST:
    {
        UINT nHitTest;
        //截取DefWindowProc消息
        nHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
        //如果鼠標左鍵按下 GetAsyncKeyState函數(shù)的返回值小于0
        if (nHitTest == HTCLIENT && GetAsyncKeyState(MK_LBUTTON) < 0)
        {
            //改變DefWindowProc消息
            nHitTest = HTCAPTION;
        }
        return nHitTest;
    }
        break;

給系統(tǒng)菜單追加菜單項

定義菜單ID
#define IDM_HELP 1001
#define IDM_TOPMOST 1002
追加菜單
case WM_CREATE:
    {
        HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);    //獲取系統(tǒng)菜單
        AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);    //添加分割線
        AppendMenu(hSysMenu, MF_STRING, IDM_TOPMOST, L"總是在前");
        AppendMenu(hSysMenu, MF_STRING, IDM_HELP, L"幫助");
    }

右鍵菜單

這個不能算是右鍵菜單,因為截取了DefWindowProc消息勾给,多以對客戶區(qū)的右鍵相當于對標題欄的右鍵彈出的是系統(tǒng)菜單

    case WM_CONTEXTMENU:
    {
        POINT pt;
        //lParam包含了鼠標的位置消息 低位x,高位y
        pt.x = LOWORD(lParam);
        pt.y = HIWORD(lParam);
        //獲取系統(tǒng)菜單
        HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
        //彈出系統(tǒng)菜單
        int nId = TrackPopupMenu(hSysMenu, TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
        if (nId > 0)
            SendMessage(hwnd, WM_SYSCOMMAND, nId, 0);
        return 0;
    }
        break;

對菜單操作進行響應

全局添加是否頂置標識符
static int s_bTopMost = 0;

響應菜單

注冊窗口的時候窗口風格必須帶上WS_SYSMENU

    case WM_SYSCOMMAND:
        {
            int nId = wParam;
            switch (nId)
            {
            case IDM_HELP:
                MessageBox(hwnd, L"一個小時鐘程序", L"幫助", 0);
                break;
            case IDM_TOPMOST://窗口頂置
            {
                HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
                if (s_bTopMost)
                {
                    //取消選中
                    CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
                    //取消頂置窗口
                    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
                    s_bTopMost = FALSE;
                }
                else
                {
                    //選中
                    CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_CHECKED);
                    //頂置
                    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
                    s_bTopMost = TRUE;
                }
                return DefWindowProc(hwnd, WM_SYSCOMMAND, nId, 0);
            }
                break;

完整代碼顯示

#include <windows.h>
#define IDM_HELP 1001
#define IDM_TOPMOST 1002

// 窗口函數(shù)的函數(shù)原形
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow)
{
    WCHAR szClassName[] = L"MainWClass";//窗口類的名稱
    WNDCLASSEX wndclass;

    // 用描述主窗口的參數(shù)填充WNDCLASSEX結(jié)構(gòu)
    wndclass.cbSize = sizeof(wndclass); // 結(jié)構(gòu)的大小
    wndclass.style = CS_HREDRAW | CS_VREDRAW;   // 指定如果大小改變就重畫
    wndclass.lpfnWndProc = MainWndProc; // 窗口函數(shù)指針
    wndclass.cbClsExtra = 0;        // 沒有額外的類內(nèi)存
    wndclass.cbWndExtra = 0;        // 沒有額外的窗口內(nèi)存
    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 = szClassName;   // 窗口類的名稱   
    wndclass.hIconSm = NULL;        // 沒有類的小圖標

                                    // 注冊這個窗口類
    RegisterClassEx(&wndclass);

    // 創(chuàng)建主窗口
    HWND hwnd = CreateWindowEx(
        0,          // dwExStyle锅知,擴展樣式   
        szClassName,        // lpClassName播急,類名           
        L"時鐘",  // lpWindowName,標題      
        WS_POPUP|WS_SYSMENU|WS_SIZEBOX, // dwStyle售睹,窗口風格 
        100,        // X桩警,初始 X 坐標        
        100,        // Y,初始 Y 坐標        
        300,        // nWidth昌妹,寬度            
        300,        // nHeight捶枢,高度           
        NULL,           // hWndParent握截,父窗口句柄         
        NULL,           // hMenu,菜單句柄       
        hInstance,      // hlnstance烂叔,程序?qū)嵗浔?    
        NULL);          // lpParam谨胞,用戶數(shù)據(jù)         

    if (hwnd == NULL)
    {
        MessageBox(NULL, L"創(chuàng)建窗口出錯!", L"error", MB_OK);
        return -1;
    }

    // 顯示窗口蒜鸡,刷新窗口客戶區(qū)
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 從消息堆中取出消息
    MSG msg;
    while (::GetMessage(&msg, NULL, 0, 0))
    {
        // 轉(zhuǎn)化鍵盤消息
        TranslateMessage(&msg);
        // 將消息發(fā)送到相應的窗口函數(shù)
        DispatchMessage(&msg);
    }

    // 當GetMessage返回0時程序結(jié)束
    return msg.wParam;
}

static int s_bTopMost = 0;
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    TCHAR szText[] = L"第一個win32程序胯努!";
    switch (message)
    {
    case WM_CREATE:
    {
        HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
        AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);    //添加分割線
        AppendMenu(hSysMenu, MF_STRING, IDM_TOPMOST, L"總是在前");
        AppendMenu(hSysMenu, MF_STRING, IDM_HELP, L"幫助");
    }
        break;
    case WM_NCHITTEST:
    {
        UINT nHitTest;
        //截取DefWindowProc消息
        nHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
        //如果鼠標左鍵按下 GetAsyncKeyState函數(shù)的返回值小于0
        if (nHitTest == HTCLIENT && GetAsyncKeyState(MK_LBUTTON) < 0)
        {
            //改變DefWindowProc消息
            nHitTest = HTCAPTION;
        }
        return nHitTest;
    }
        break;
    case WM_CONTEXTMENU:
    {
        POINT pt;
        //lParam包含了鼠標的位置消息 低位x,高位y
        pt.x = LOWORD(lParam);
        pt.y = HIWORD(lParam);
        //獲取系統(tǒng)菜單
        HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
        //彈出系統(tǒng)菜單
        int nId = TrackPopupMenu(hSysMenu, TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
        if (nId > 0)
            SendMessage(hwnd, WM_SYSCOMMAND, nId, 0);
        return 0;
    }
        break;
    case WM_SYSCOMMAND:
        {
            int nId = wParam;
            switch (nId)
            {
            case IDM_HELP:
                MessageBox(hwnd, L"一個小時鐘程序", L"幫助", 0);
                break;
            case IDM_TOPMOST://窗口頂置
            {
                HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
                if (s_bTopMost)
                {
                    //取消選中
                    CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
                    //取消頂置窗口
                    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
                    s_bTopMost = FALSE;
                }
                else
                {
                    //選中
                    CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_CHECKED);
                    //頂置
                    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
                    s_bTopMost = TRUE;
                }
                return DefWindowProc(hwnd, WM_SYSCOMMAND, nId, 0);
            }
                break;
            default:
                break;
            }
        }
        break;
    case WM_PAINT: // 窗口客戶區(qū)需要重畫
    {
        HDC hdc;
        PAINTSTRUCT ps;
        // 使無效的客戶區(qū)變的有效逢防,并取得設(shè)備環(huán)境句柄
        hdc = BeginPaint(hwnd, &ps);
        // 顯示文字
        //TextOut(hdc, 10, 10, szText, wcslen(szText));
        EndPaint(hwnd, &ps);
        return 0;
    }
    case WM_DESTROY: // 正在銷毀窗口
        // 向消息隊列投遞一個WM_QUIT消息叶沛,促使GetMessage函數(shù)返回0,結(jié)束消息循環(huán)
        PostQuitMessage(0);
        return 0;
    }
    // 將我們不處理的消息交給系統(tǒng)做默認處理
    return DefWindowProc(hwnd, message, wParam, lParam);
}

設(shè)置坐標

case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

            //獲取客戶區(qū)大小
            RECT rt;
            GetClientRect(hWnd, &rt);
            int cx = rt.right;
            int cy = rt.bottom;

            SetViewportExtEx(hdc, cx, cy, NULL);    //設(shè)置x,y坐標軸
            SetViewportOrgEx(hdc, 0, 0, NULL);      //設(shè)置原點
            EndPaint(hWnd, &ps);
        }

了解這些win32基礎(chǔ)知識之后我們來繪制一個數(shù)字時鐘

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末忘朝,一起剝皮案震驚了整個濱河市灰署,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌局嘁,老刑警劉巖溉箕,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異导狡,居然都是意外死亡约巷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門旱捧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來独郎,“玉大人,你說我怎么就攤上這事枚赡∶グ” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵贫橙,是天一觀的道長贪婉。 經(jīng)常有香客問我,道長卢肃,這世上最難降的妖魔是什么疲迂? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮莫湘,結(jié)果婚禮上尤蒿,老公的妹妹穿的比我還像新娘。我一直安慰自己幅垮,他們只是感情好腰池,可當我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般示弓。 火紅的嫁衣襯著肌膚如雪讳侨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天奏属,我揣著相機與錄音跨跨,去河邊找鬼。 笑死拍皮,一個胖子當著我的面吹牛歹叮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铆帽,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼咆耿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了爹橱?” 一聲冷哼從身側(cè)響起萨螺,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎愧驱,沒想到半個月后慰技,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡组砚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年吻商,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糟红。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡艾帐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盆偿,到底是詐尸還是另有隱情柒爸,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布事扭,位于F島的核電站捎稚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏求橄。R本人自食惡果不足惜今野,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罐农。 院中可真熱鬧腥泥,春花似錦、人聲如沸啃匿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溯乒。三九已至夹厌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裆悄,已是汗流浹背矛纹。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留光稼,地道東北人或南。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像艾君,于是被迫代替她去往敵國和親采够。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,781評論 2 361