🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Windows API 中的系统函数 > 原文: [http://zetcode.com/gui/winapi/system/](http://zetcode.com/gui/winapi/system/) 在 Windows API 教程的这一部分中,我们介绍了系统函数。 系统函数接收有关系统的信息并以各种方式与系统通信。 ## 屏幕大小 `GetSystemMetrics()`函数检索各种系统指标和系统配置设置。 `screen_size.c` ```c #include <windows.h> #include <wchar.h> #pragma comment(lib, "user32.lib") int wmain(void) { int x = GetSystemMetrics(SM_CXSCREEN); int y = GetSystemMetrics(SM_CYSCREEN); wprintf(L"The screen size is: %dx%d\n", x, y); return 0; } ``` 该代码示例将屏幕大小输出到控制台。 ```c #pragma comment(lib, "user32.lib") ``` 该程序需要`user32.lib`库进行编译。 ```c int x = GetSystemMetrics(SM_CXSCREEN); int y = GetSystemMetrics(SM_CYSCREEN); ``` 我们用`GetSystemMetrics()`确定屏幕分辨率。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\ScreenSize>ScreenSize.exe The screen size is: 1280x800 ``` 屏幕大小为`1280x800`。 ## 锁定工作站 `LockWorkStation()`锁定工作站的显示。 `lock_workstation.c` ```c #include <windows.h> #include <wchar.h> #pragma comment(lib, "user32.lib") int wmain(void) { int r = LockWorkStation(); if( r == 0 ) { wprintf(L"LockWorkStation() failed %d\n", GetLastError()); return 1; } return 0; } ``` 该程序需要`user32.lib`进行编译。 ## 电脑名称 `GetComputerNameEx()`函数检索与本地计算机关联的 NetBIOS 或 DNS 名称。 名称是在系统启动时建立的。 `computer_name.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = sizeof(computerName) / sizeof(computerName[0]); int r = GetComputerNameW(computerName, &size); if (r == 0) { wprintf(L"Failed to get computer name %ld", GetLastError()); return 1; } wprintf(L"Computer name: %ls\n", computerName); return 0; } ``` 该示例将计算机名称打印到控制台。 ```c wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1]; ``` `MAX_COMPUTERNAME_LENGTH`常数确定计算机名称的最大长度。 ```c int r = GetComputerNameW(computerName, &size); ``` 我们使用`GetComputerNameW()`函数获得计算机的名称。 名称存储在`computerName`数组中。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\ComputerName>ComputerName.exe Computer name: ANDROMEDA ``` 我们运行代码示例。 ## 用户名 `GetUserNameW()`函数返回用户名。 `username.c` ```c #include <windows.h> #include <Lmcons.h> #include <wchar.h> int wmain(void) { wchar_t username[UNLEN+1]; DWORD len = sizeof(username) / sizeof(wchar_t); int r = GetUserNameW(username, &len); if (r == 0) { wprintf(L"Failed to get username %ld", GetLastError()); return 1; } wprintf(L"User name: %ls\n", username); return 0; } ``` 该示例将用户名打印到控制台。 ```c #include <Lmcons.h> ``` `Lmcons.h`文件具有`ULEN`常量的定义。 ```c wchar_t username[UNLEN+1]; ``` `ULEN`常量定义用户名的最大长度。 ```c int r = GetUserNameW(username, &len); ``` `GetUserNameW()`函数检索用户名并将其存储到`username`数组中。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\Username>username.exe User name: Jano ``` 这是`username.exe`程序的示例输出。 ## 当前目录 当前目录是用户所在或正在使用的目录。 在 Windows API 中,`SetCurrentDirectoryW()`更改当前目录,`GetCurrentDirectoryW()`检索当前目录。 `current_directory.c` ```c #include <windows.h> #include <wchar.h> #define BUFSIZE MAX_PATH int wmain(int argc, wchar_t **argv) { wchar_t buf[BUFSIZE]; if(argc != 2) { wprintf(L"Usage: %ls <dir>\n", argv[0]); return 1; } DWORD r = SetCurrentDirectoryW(argv[1]); if (r == 0) { wprintf(L"SetCurrentDirectoryW() failed (%ld)\n", GetLastError()); return 1; } r = GetCurrentDirectoryW(BUFSIZE, buf); if (r == 0) { wprintf(L"GetCurrentDirectoryW() failed (%ld)\n", GetLastError()); return 1; } if (r > BUFSIZE) { wprintf(L"Buffer too small; needs %d characters\n", r); return 1; } wprintf(L"Current directory is: %ls\n", buf); return 0; } ``` 在代码示例中,我们更改并打印当前工作目录。 该程序接收一个命令行参数-要更改的目录。 ```c #define BUFSIZE MAX_PATH ``` 我们使用`MAX_PATH`常量,该常量定义系统路径的最大长度。 ```c if(argc != 2) { wprintf(L"Usage: %ls <dir>\n", argv[0]); return 1; } ``` 如果我们不将参数传递给程序,则会显示一条错误消息。 ```c DWORD r = SetCurrentDirectoryW(argv[1]); ``` 我们使用`SetCurrentDirectoryW()`切换到目录,该目录作为参数传递。 ```c r = GetCurrentDirectoryW(BUFSIZE, buf); ``` 通过`GetCurrentDirectoryW()`函数调用获取当前的工作目录。 ```c if (r > BUFSIZE) { wprintf(L"Buffer too small; needs %d characters\n", r); return 1; } ``` 如果返回的值大于`BUFSIZE`,则缓冲区太小。 ## Windows 版本 版本帮助器函数可用于确定当前的操作系统版本。 `windows_version.c` ```c #include <windows.h> #include <wchar.h> #include <VersionHelpers.h> int wmain(void) { //if (IsWindows10OrGreater()) { // wprintf(L"This is Windows 10+"); // } if (IsWindows8Point1OrGreater()) { wprintf(L"This is Windows 8.1+\n"); } else if (IsWindows8OrGreater()) { wprintf(L"This is Windows 8\n"); } else if (IsWindows7OrGreater ()) { wprintf(L"This is Windows 7\n"); } else if (IsWindowsVistaOrGreater ()) { wprintf(L"This is Windows Vista\n"); } else if (IsWindowsXPOrGreater()) { wprintf(L"This is Windows XP\n"); } return 0; } ``` 我们使用版本帮助器函数来确定操作系统版本。 ```c #include <VersionHelpers.h> ``` 辅助函数在`VersionHelpers.h`文件中声明。 ```c //if (IsWindows10OrGreater()) { // wprintf(L"This is Windows 10+"); // } ``` 在撰写本文时,Pelles C 在其 SDK 中尚未定义`IsWindows10OrGreater()`。 ```c if (IsWindows8Point1OrGreater()) { wprintf(L"This is Windows 8.1+\n"); } ``` 如果当前版本为 Windows 8.1 或更高版本,则`IsWindows8Point1OrGreater()`返回 true。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\WindowsVersion>WindowsVersion.exe This is Windows 7 ``` 这是程序的示例输出。 ## 内存 `GlobalMemoryStatusEx()`检索有关系统当前对物理和虚拟内存使用情况的信息。 `memory.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { MEMORYSTATUSEX mem = {0}; mem.dwLength = sizeof(mem); int r = GlobalMemoryStatusEx(&mem); if (r == 0) { wprintf(L"Failed to memory status %ld", GetLastError()); return 1; } wprintf(L"Memory in use: %ld percent\n", mem.dwMemoryLoad); wprintf(L"Total physical memory: %lld\n", mem.ullTotalPhys); wprintf(L"Free physical memory: %lld\n", mem.ullAvailPhys); wprintf(L"Total virtual memory: %lld\n", mem.ullTotalVirtual); wprintf(L"Free virtual memory: %lld\n", mem.ullAvailVirtual); return 0; } ``` 该程序将有关内存使用情况的统计信息打印到控制台。 ```c MEMORYSTATUSEX mem = {0}; ``` `GlobalMemoryStatusEx()`函数在`MEMORYSTATUSEX`结构中存储有关内存状态的信息。 ```c int r = GlobalMemoryStatusEx(&mem); ``` `GlobalMemoryStatusEx()`函数被执行; 信息存储在结构中。 ```c wprintf(L"Memory in use: %ld percent\n", mem.dwMemoryLoad); ``` `dwMemoryLoad`成员指定正在使用的物理内存的大约百分比。 ```c wprintf(L"Total physical memory: %lld\n", mem.ullTotalPhys); ``` `ullTotalPhys`成员以字节为单位指定实际的物理内存。 ```c wprintf(L"Free physical memory: %lld\n", mem.ullAvailPhys); ``` `ullTotalPhys`成员以字节为单位指定当前可用的物理内存量。 ```c wprintf(L"Total virtual memory: %lld\n", mem.ullTotalVirtual); ``` `ullTotalVirtual`成员以字节为单位指定虚拟内存总量。 ```c wprintf(L"Free virtual memory: %lld\n", mem.ullAvailVirtual); ``` `ullAvailVirtual`成员以字节为单位指定可用虚拟内存量。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\Memory>Memory.exe Memory in use: 47 percent Total physical memory: 4226072576 Free physical memory: 2229788672 Total virtual memory: 8796092891136 Free virtual memory: 8796052586496 ``` 这是程序的示例输出。 ## 已知数据夹 从 Windows Vista 开始,使用新系统来标识 Windows 中的重要目录。 它被称为已知文件夹。 已知文件夹使用一组 GUID(全局唯一标识符)值来引用重要文件夹。 `SHGetKnownFolderPath()`函数检索由文件夹 ID 标识的已知文件夹的完整路径。 `documents_dir.c` ```c #include <windows.h> #include <initguid.h> #include <KnownFolders.h> #include <ShlObj.h> #include <wchar.h> int wmain(void) { PWSTR path = NULL; HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &path); if (SUCCEEDED(hr)) { wprintf(L"%ls\n", path); } CoTaskMemFree(path); return 0; } ``` 该示例确定用户的`Documents`目录的完整路径。 我们需要将`shell32.lib`和`ole32.lib`添加到项目库中。 ```c #include <initguid.h> ``` 由于某些内部 API 问题,我们需要包含`initguid.h`文件; 否则,该示例将无法编译。 它失败,并显示`Unresolved external symbol 'FOLDERID_Documents'`错误。 ```c HRESULT hr = SHGetKnownFolderPath(&FOLDERID_Documents, 0, NULL, &path); ``` `SHGetKnownFolderPath()`用于确定文档目录的路径。 ```c if (SUCCEEDED(hr)) { wprintf(L"%ls\n", path); } ``` `SUCCEEDED`宏可用于确定函数调用是否成功。 ```c CoTaskMemFree(path); ``` 最后,必须使用`CoTaskMemFree()`函数释放分配的内存。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\DocumentsDir>DocumentsDir.exe C:\Users\Jano\Documents ``` 这是`DocumentsDir.exe`程序的示例输出。 ## 驱动器名称 `GetLogicalDriveStringsW()`函数使用指定系统中有效驱动器的字符串填充缓冲区。 `get_drives.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { wchar_t LogicalDrives[MAX_PATH] = {0}; DWORD r = GetLogicalDriveStringsW(MAX_PATH, LogicalDrives); if (r == 0) { wprintf(L"Failed to get drive names %ld", GetLastError()); return 1; } if (r > 0 && r <= MAX_PATH) { wchar_t *SingleDrive = LogicalDrives; while(*SingleDrive) { wprintf(L"%ls\n", SingleDrive); SingleDrive += wcslen(SingleDrive) + 1; } } return 0; } ``` 该示例打印系统中的有效驱动器。 ```c wchar_t LogicalDrives[MAX_PATH] = {0}; ``` 驱动器名称是路径类型,因此`MAX_PATH`常量与其最大长度有关。 `LogicalDrives`是一个字符串数组,用作`GetLogicalDriveStringsW()`函数的缓冲区。 ```c DWORD r = GetLogicalDriveStringsW(MAX_PATH, LogicalDrives); ``` `GetLogicalDriveStringsW()`被调用。 缓冲区中填充了以零结尾的字符串,这些字符串代表设备名称。 该函数的第一个参数是指定缓冲区的最大大小。 缓冲区是第二个参数。 ```c wchar_t *SingleDrive = LogicalDrives; while(*SingleDrive) { wprintf(L"%ls\n", SingleDrive); SingleDrive += wcslen(SingleDrive) + 1; } ``` 我们遍历设备名称数组并将其打印到控制台。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\GetDrives>GetDrives.exe C:\ D:\ ``` 系统上有两个驱动器:`C:\`和`D:\`。 ## 可用空间 `GetDiskFreeSpaceExW()`检索有关磁盘卷上可用空间量的信息。 该函数提供三段信息:总空间量,可用空间量以及与调用线程关联的用户可用的可用空间。 `free_disk_space.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { unsigned __int64 freeCall, total, free; int r = GetDiskFreeSpaceExW(L"C:\\", (PULARGE_INTEGER) &freeCall, (PULARGE_INTEGER) &total, (PULARGE_INTEGER) &free); if (r == 0) { wprintf(L"Failed to get free disk space %ld", GetLastError()); return 1; } wprintf(L"Available space to caller: %I64u MB\n", freeCall / (1024*1024)); wprintf(L"Total space: %I64u MB\n", total / (1024*1024)); wprintf(L"Free space on drive: %I64u MB\n", free / (1024*1024)); return 0; } ``` 该示例检查`C:\`驱动器上的磁盘空间。 ```c unsigned __int64 freeCall, total, free; ``` 数量以字节为单位; 这些数字可能非常大。 使用`unsigned __int64`类型,它是一个能够存储非常大的值的正 64 位整数。 ```c int r = GetDiskFreeSpaceExW(L"C:\\", (PULARGE_INTEGER) &freeCall, (PULARGE_INTEGER) &total, (PULARGE_INTEGER) &free); ``` `GetDiskFreeSpaceExW()`被调用。 ```c wprintf(L"Available space to caller: %I64u MB\n", freeCall / (1024*1024)); wprintf(L"Total space: %I64u MB\n", total / (1024*1024)); wprintf(L"Free space on drive: %I64u MB\n", free / (1024*1024)); ``` 使用`wprintf()`函数将这三个金额打印到控制台。 这些值以 MB 表示。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\FreeDiskSpace>FreeDiskSpace.exe Available space to caller: 20377 MB Total space: 69999 MB Free space on drive: 20377 MB ``` 这是`FreeDiskSpace.exe`程序的示例输出。 ## CPU 速度 可以通过检查注册表值来确定 CPU 速度。 该值将在安装过程中写入注册表。 我们需要查询`HARDWARE\DESCRIPTION\System\CentralProcessor\0`键。 `cpu_speed.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { DWORD BufSize = MAX_PATH; DWORD mhz = MAX_PATH; HKEY key; long r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &key); if (r != ERROR_SUCCESS) { wprintf(L"RegOpenKeyExW() failed %ld", GetLastError()); return 1; } r = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE) &mhz, &BufSize); if (r != ERROR_SUCCESS) { wprintf(L"RegQueryValueExW() failed %ld", GetLastError()); return 1; } wprintf(L"CPU speed: %lu MHz\n", mhz); r = RegCloseKey(key); if (r != ERROR_SUCCESS) { wprintf(L"Failed to close registry handle %ld", GetLastError()); return 1; } return 0; } ``` 该示例确定 CPU 速度。 ```c long r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &key); ``` `RegOpenKeyExW()`函数用于打开提供的注​​册表项。 ```c r = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE) &mhz, &BufSize); ``` 通过`RegQueryValueExW()`函数读取该值。 ```c r = RegCloseKey(key); ``` `RegCloseKey()`关闭注册表句柄。 ```c C:\Users\Jano\Documents\Pelles C Projects\system\CpuSpeed>CpuSpeed.exe CPU speed: 2394 MHz ``` 这是`CpuSpeed.exe`程序的示例输出。 在 Windows API 教程的这一部分中,我们使用了一些系统函数。