V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
juxiuyu123
V2EX  ›  程序员

程序猿的酷炫屏保

  •  
  •   juxiuyu123 · 2015-12-13 05:54:36 +08:00 · 3884 次点击
    这是一个创建于 3273 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include "stdafx.h"
    #include <windows.h>
    #define ID_TIMER 1
    #define STRMAXLEN 25 //一个显示列的最大长度
    #define STRMINLEN 8 //一个显示列的最小长度


    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    //////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////
    typedef struct tagCharChain //整个当作屏幕的一个显示列,这是个双向列表
    {
    struct tagCharChain *prev; //链表的前个元素
    TCHAR ch; //一个显示列中的一个字符
    struct tagCharChain *next; //链表的后个元素
    }CharChain, *pCharChain;

    typedef struct tagCharColumn
    {
    CharChain *head, *current, *point;
    int x, y, iStrLen; //显示列的开始显示的 x,y 坐标,iStrLen 是这个列的长度
    int iStopTimes, iMustStopTimes; //已经停滞的次数和必须停滞的次数,必须停滞的次数是随机的
    }CharColumn, *pCharColumn;

    int main(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
    {
    static TCHAR szAppName[] = TEXT ("matrix") ;
    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 (BLACK_BRUSH) ;
    wndclass.lpszMenuName = NULL ;
    wndclass.lpszClassName = szAppName ;

    if(!RegisterClass (&wndclass))
    {
    MessageBox (NULL, TEXT ("此程序必须运行在 NT 下!"), szAppName, MB_IC ONERROR) ;
    return 0;
    }

    hwnd = CreateWindow (szAppName, NULL,
    WS_DLGFRAME | WS_THICKFRAME | WS_POPUP,
    0, 0,
    GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
    NULL, NULL, hInstance,
    NULL) ;

    ShowWindow (hwnd, SW_SHOWMAXIMIZED) ; //最大化显示
    UpdateWindow (hwnd) ;
    ShowCursor(FALSE); //隐藏鼠标光标

    srand ((int) GetCurrentTime ()) ; //初始化随机数发生器
    while (GetMessage (&msg, NULL, 0, 0))
    {
    TranslateMessage (&msg) ;
    DispatchMessage (&msg) ;
    }
    ShowCursor(TRUE); //显示鼠标光标
    return msg.wParam ;
    }

    TCHAR randomChar() //随机字符产生函数
    {
    return (TCHAR)(rand()%(126-33)+33); //33 到 126 之间
    }

    int init(CharColumn *cc, int cyScreen, int x) //初始化
    {
    int j;
    cc->iStrLen = rand()%(STRMAXLEN-STRMINLEN) + STRMINLEN; //显示列的长度
    cc->x = x+3 ; //显示列的开始显示的 x 坐标
    cc->y =rand()%3?rand()%cyScreen:0; //显示列的开始显示的 y 坐标
    cc->iMustStopTimes = rand()%6 ;
    cc->iStopTimes = 0 ;
    cc->head = cc->current =
    (pCharChain)calloc(cc->iStrLen, sizeof(CharChain)); //生成显示列
    for(j=0; j<cc->iStrLen-1; j++)
    {
    cc->current->prev = cc->point; //cc->point 一个显示列的前个元素
    cc->current->ch = '\0';
    cc->current->next = cc->current+1; //cc->current+1 一个显示列的后个元素
    cc->point = cc->current++; //cc->point = cc->current; cc->current++;
    }
    cc->current->prev = cc->point; //最后一个节点
    cc->current->ch = '\0';
    cc->current->next = cc->head;
    cc->head->prev = cc->current; //头节点的前一个为此链的最后一个元素

    cc->current = cc->point = cc->head; //free 掉申请的内存要用 current 当参数
    cc->head->ch = randomChar(); // 对链表头的 元素填充
    return 0;
    }

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    HDC hdc ;
    //ctn 用来确定一个显示链是否 向下前进,如果等待次数超过必须等待的次数,ctn 就代表要向下前进
    int i, j, temp, ctn; //j 为一个显示链中除链表头外的在屏幕上显示的 y 坐标,temp 绿色过度到黑色之用
    static HDC hdcMem;
    HFONT hFont;
    static HBITMAP hBitmap;
    static int cxScreen, cyScreen; //屏幕的宽度 高度.
    static int iFontWidth=10, iFontHeight=15, iColumnCount; //字体的宽度 高度, 列数
    static CharColumn *ccChain;

    switch (message)
    {
    case WM_CREATE:
    cxScreen = GetSystemMetrics(SM_CXSCREEN) ; //屏幕宽度
    cyScreen = GetSystemMetrics(SM_CYSCREEN) ;
    SetTimer (hwnd, ID_TIMER, 10, NULL) ;

    hdc = GetDC(hwnd);
    hdcMem = CreateCompatibleDC(hdc);
    hBitmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen);
    SelectObject(hdcMem, hBitmap);
    ReleaseDC(hwnd, hdc);
    //创建字体
    hFont = CreateFont(iFontHeight, iFontWidth-5, 0, 0, FW_BOLD, 0, 0, 0,
    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
    DRAFT_QUALITY, FIXED_PITCH | FF_SWISS, TEXT("Fixedsys"));
    SelectObject(hdcMem, hFont);
    DeleteObject (hFont) ;
    SetBkMode(hdcMem, TRANSPARENT); //设置背景模式为 透明
    iColumnCount = cxScreen/(iFontWidth*3/2); //屏幕所显示字母雨的列数

    ccChain = (pCharColumn)calloc(iColumnCount, sizeof(CharColumn));
    for(i=0; i<iColumnCount; i++)
    {
    init(ccChain+i, cyScreen, (iFontWidth*3/2)*i);
    }
    return 0 ;

    case WM_TIMER:
    hdc = GetDC(hwnd);
    PatBlt (hdcMem, 0, 0, cxScreen, cyScreen, BLACKNESS) ; //将内存设备映像刷成黑色
    for(i=0; i<iColumnCount; i++)
    {
    ctn = (ccChain+i)->iStopTimes++ > (ccChain+i)->iMustStopTimes;
    //
    (ccChain+i)->point = (ccChain+i)->head; //point 用于遍历整个显示列

    //第一个字符显示为 白色
    SetTextColor(hdcMem, RGB(255, 255, 255));
    TextOut(hdcMem, (ccChain+i)->x, (ccChain+i)->y, &((ccChain+i)->point->ch), 1);
    j = (ccChain+i)->y;
    (ccChain+i)->point = (ccChain+i)->point->next;
    //遍历整个显示列,将这个显示列里的字符从下往上显示
    temp = 0 ; //temp 绿色过度到黑色之用
    while((ccChain+i)->point != (ccChain+i)->head && (ccChain+i)->point->ch)
    {
    SetTextColor(hdcMem, RGB(0, 255-(255*(temp++)/(ccChain+i)->iStrLen), 0));
    TextOut(hdcMem, (ccChain+i)->x, j-=iFontHeight, &((ccChain+i)->point->ch), 1);
    (ccChain+i)->point = (ccChain+i)->point->next;
    }
    if(ctn)
    (ccChain+i)->iStopTimes = 0 ;
    else continue;
    (ccChain+i)->y += iFontHeight; //下次开始显示的 y 坐标 为当前的 y 坐标加上 一个字符的高度
    //如果开始显示的 y 坐标减去 整个显示列的长度超过了屏幕的高度
    if( (ccChain+i)->y-(ccChain+i)->iStrLen*iFontHeight > cyScreen)
    {
    free( (ccChain+i)->current );
    init(ccChain+i, cyScreen, (iFontWidth*3/2)*i);
    }
    //链表的头 为此链表的前个元素,因为下次开始显示的时候 就相当与在整个显示列的开头添加个元素,然后在开始往上显示
    (ccChain+i)->head = (ccChain+i)->head->prev;
    (ccChain+i)->head->ch = randomChar();
    }

    BitBlt(hdc, 0, 0, cxScreen, cyScreen, hdcMem, 0, 0, SRCCOPY);
    ReleaseDC(hwnd, hdc);
    return 0;

    case WM_RBUTTONDOWN:
    KillTimer (hwnd, ID_TIMER) ;
    return 0;

    case WM_RBUTTONUP:
    SetTimer (hwnd, ID_TIMER, 10, NULL) ;
    return 0;

    //处理善后工作
    case WM_KEYDOWN: // 按下键盘任意键
    case WM_LBUTTONDOWN: //鼠标双击
    case WM_DESTROY:
    KillTimer (hwnd, ID_TIMER) ;
    DeleteObject(hBitmap);
    DeleteDC(hdcMem);
    for(i=0; i<iColumnCount; i++)
    {
    free( (ccChain+i)->current );
    }
    free(ccChain);
    PostQuitMessage (0) ;
    return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    14 条回复    2015-12-14 00:13:35 +08:00
    vibbow
        1
    vibbow  
       2015-12-13 06:34:06 +08:00
    没看代码
    但是看标题,猜测不会是黑客帝国那种效果把...
    hqs123
        2
    hqs123  
       2015-12-13 08:08:14 +08:00
    楼主是编程高手啊...
    greatghoul
        3
    greatghoul  
       2015-12-13 09:47:43 +08:00
    楼主不如直接给个 gist 链接 ,你这排版一点也不炫。
    Jeremial
        4
    Jeremial  
       2015-12-13 10:54:20 +08:00
    请使用 cmatrix
    Ouyangan
        5
    Ouyangan  
       2015-12-13 10:55:10 +08:00
    编码风格,我头痛~
    Karblue
        6
    Karblue  
       2015-12-13 11:34:37 +08:00 via Android
    不用看了。字母雨效果
    harry890829
        7
    harry890829  
       2015-12-13 12:03:00 +08:00
    windows 的……
    loading
        8
    loading  
       2015-12-13 12:22:25 +08:00 via Android
    楼主你知道这样贴是没人看的吗?
    tangbao
        9
    tangbao  
       2015-12-13 17:39:31 +08:00
    LZ , stdafx.h 这个头文件是不是只有 vc++才有的啊?
    Barnet
        10
    Barnet  
       2015-12-13 20:27:42 +08:00
    没看评论,我估也是黑客帝国那种效果
    haogefeifei
        11
    haogefeifei  
       2015-12-13 21:50:40 +08:00
    看见 windows.h 。我默默的不说话了。。。
    icedx
        12
    icedx  
       2015-12-13 23:44:30 +08:00
    Windows 还是 MFC 啧啧
    exoticknight
        13
    exoticknight  
       2015-12-13 23:51:11 +08:00
    除了黑客帝国还能怎么酷炫?
    matthewz
        14
    matthewz  
       2015-12-14 00:13:35 +08:00 via iPhone
    誰還看 mfc
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1035 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:19 · PVG 05:19 · LAX 13:19 · JFK 16:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.