当前位置: 首页
AI教程
黑客帝国经典屏保源码

黑客帝国经典屏保源码

热心网友 时间:2026-07-03
转载

聊一个经典老梗:电影《黑客帝国》里那满屏绿色数字雨的屏保效果,当年是多少人对着电脑屏幕发呆时的标配回忆。虽然现在系统自带的屏保已经不错,但亲手写代码、编译成.scr文件,再设置到桌面上,那种成就感完全不一样。下面把整个流程拆开讲,从代码到最终设置,一步不落。

前期准备

开发环境用Visual Studio 2010或更高版本就行。打开VS,新建项目,选择Visual C++下的Win32控制台应用程序,项目名称填写"hacker"——名字随意,但后面需要对着这个文件名操作。

粘贴代码

项目创建好后,把下面这段源码复制到主源文件里(通常是"hacker.cpp")。这段代码是一位叫Wicrecend的程序员写的数字流星雨效果,核心思路是用双向链表维护每一列字符的滚动状态,通过定时器逐帧刷新屏幕,配合随机字符和颜色渐变,实现经典的矩阵雨特效。

//数字流星雨 作者:Wicrecend
#include "stdafx.h"
#include  
#define ID_TIMER 1
#define STRMAXLEN 25 //一个显示列的最大长度 
#define STRMINLEN 8//一个显示列的最小长度
#pragma comment ( linker, "/subsystem:windows /entry:mainCRTStartup" ) //去除启动或退出程序时黑框 
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_ICONERROR) ; 
        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; jiStrLen-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 ; 
    int i, j, temp, ctn; 
    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; iiStopTimes ++ > (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; icurrent ); 
            } 
            free(ccChain); 
            PostQuitMessage (0) ; 
            return 0 ; 
    } 
    return DefWindowProc (hwnd, message, wParam, lParam) ; 
}

编译与链接

代码粘贴进去后,直接按F7(或者点击生成→生成解决方案),确保编译没有错误。如果提示找不到"stdafx.h",检查一下项目属性里是否设置了预编译头,或者直接把那行#include注释掉也可以(因为代码里其实并没有用到预编译头中的内容)。

转换为屏保文件

编译成功之后,在项目输出目录(比如Debug或Release文件夹)中找到"hacker.exe"。把这个文件重命名,将后缀.exe改为.scr,变成"hacker.scr"。这一步是Windows屏保的硬性要求——屏保本质上就是一个可执行文件,只不过后缀必须为.scr。

安装到系统目录

将改好名的"hacker.scr"文件复制到C:\Windows\System32目录下(如果是64位系统且屏保是32位,也可以放在C:\Windows\SysWOW64,但通常放在System32即可)。复制时可能需要管理员权限,确认授权就好。

设置屏保

接下来就是常规操作了:在桌面空白处右键→个性化→锁屏界面→屏幕保护程序设置(或者直接搜索“更改屏幕保护程序”)。在下拉菜单里应该就能找到"hacker"这个选项,选中它,预览一下效果,然后点击应用和确定。

大功告成。当你离开电脑几分钟,屏幕就会自动下起绿色的数字雨——而且是你亲手编译出来的雨。

\

来源:https://developer.aliyun.com/article/8576

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
批处理BAT入门教程第一篇

批处理BAT入门教程第一篇

提供13个批处理实战技巧,覆盖全盘查找并删除文件夹或文件、拷贝移动文件、创建畸形文件夹及设置隐藏属性等场景,可一键完成系统维护与文件管理工作,极大提升自动化操作效率和便捷性。

时间:2026-07-03 16:15
从零开始批处理命令For循环详解与实战案例

从零开始批处理命令For循环详解与实战案例

批处理For命令支持 d、 l、 r、 f四个参数。 d仅列出当前目录下的目录名; r递归搜索指定路径及其子目录中的文件; l生成数值序列; f可解析文件、字符串或命令输出,通过delims、tokens、skip、eol等选项灵活处理内容。

时间:2026-07-03 16:14
批评你的人是你生命中的贵人

批评你的人是你生命中的贵人

批评你的人往往最值得珍惜,因为他们关注你、助你成长。面对批评应包容反思,用行动改进而非辩解。接受批评是自我完善的过程,能让人少走弯路,避免重复犯错。这样的人正是生命中的贵人,值得感恩与珍惜。

时间:2026-07-03 16:14
测试人员角色定位与职责详解

测试人员角色定位与职责详解

测试人员角色经历了从找问题、保证质量到分析风险的转变,最终核心职责是提供关键信息,协助团队创造优秀产品。这包括识别问题、评估风险及帮助团队了解项目状态,而非单纯把关或追求完美。

时间:2026-07-03 16:14
经营成功测试生涯的实用方法与策略

经营成功测试生涯的实用方法与策略

一、测试生涯的起点 1989年,我在田纳西大学攻读研究生时,意外地从软件开发人员转行成为一名软件测试工程师。这并非我主动选择,说起来还有些戏剧性——某个早晨,教授质问我为何缺席那么多开发会议,我解释说这些会议总是安排在周末早上,对我这个第一次离家、刚入学的学生来说实在不便。结果呢?等待我的不是解聘通

时间:2026-07-03 16:14
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜