Windows API 之 SetDlgItemTextA

本文详细介绍了Windows API中的SetDlgItemTextA函数,主要用于设置Dialog控件的文本内容,例如TextEdit的显示文本。文章提供官方说明并附有源码示例,帮助开发者理解和应用该函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

旧题回顾: Windows API 之 EndDialog

SetDlgItemTextA

SetDlgItemTextA,用于设置Dialog组件内容,如TextEdit的文本 官方说明

函数原型:
        BOOL SetDlgItemTextA(
            [in] HWND   hDlg,  //句柄
            [in] int    nIDDlgItem, //组件ID
            [in] LPCSTR lpString  //内容
        );
用例:
    SetDlgItemTextA(hModule, IDC_EDIT1, "Hello World!");

源码示例:
开发工具:Visual Studio 2022
开发语言:C++(空项目)
字符集环境:多字节字符集(包含了ASCII)
#include <Windows.h> #include <Wbemidl.h> #include <comdef.h> #include <WinCrypt.h> #include <string> #include <algorithm> #include <sstream> #include <vector> #include <commctrl.h> #include <iomanip> // 添加缺失的头文件 #pragma comment(lib, "wbemuuid.lib") #pragma comment(lib, "Advapi32.lib") #pragma comment(lib, "Crypt32.lib") #pragma comment(lib, "comctl32.lib") // 资源ID定义 #define IDD_MAIN_DIALOG 101 // 添加缺失的定义 #define IDC_MACHINE_CODE 1001 #define IDC_DAYS_COMBO 1002 #define IDC_REG_CODE 1003 #define IDC_GENERATE_BTN 1004 #define IDC_REGISTER_BTN 1005 #define IDC_STATUS_TEXT 1006 #define IDC_VALIDATE_BTN 1007 // 全局变量 HWND g_hMainDlg = NULL; char g_szMachineCode[256] = { 0 }; // 函数声明 const char* GetMachineCode(); const char* ComputeRegistration(const char* machineCode, int daysChoice); BOOL SaveRegistration(const char* machineCode, const char* regCode, int daysChoice); int ValidateLicense(); void UpdateStatus(const char* message); void InitializeControls(HWND hDlg); void GenerateRegistrationCode(HWND hDlg); void RegisterProduct(HWND hDlg); void ValidateLicenseOnStartup(); // 获取机器码函数 const char* GetMachineCode() { if (g_szMachineCode[0] != '\0') { return g_szMachineCode; } HRESULT hres; std::string serials; // 初始化COM hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return "COM Init Failed"; } // 设置COM安全级别 hres = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); if (FAILED(hres)) { CoUninitialize(); return "CoInitializeSecurity Failed"; } // 创建WMI实例 IWbemLocator* pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc ); if (FAILED(hres)) { CoUninitialize(); return "WbemLocator Failed"; } // 连接到WMI IWbemServices* pSvc = NULL; hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc ); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return "ConnectServer Failed"; } // 设置代理安全级别 hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return "SetProxyBlanket Failed"; } // 查询CPU信息 IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Processor"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator ); if (SUCCEEDED(hres)) { IWbemClassObject* pclsObj = NULL; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) break; VARIANT vtProp; hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { serials += _bstr_t(vtProp.bstrVal); VariantClear(&vtProp); } pclsObj->Release(); } pEnumerator->Release(); } // 查询磁盘信息 hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_DiskDrive"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator ); if (SUCCEEDED(hres)) { IWbemClassObject* pclsObj = NULL; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) break; VARIANT vtProp; hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { serials += _bstr_t(vtProp.bstrVal); VariantClear(&vtProp); } pclsObj->Release(); } pEnumerator->Release(); } // 清理资源 pSvc->Release(); pLoc->Release(); CoUninitialize(); // 生成哈希值 HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; BYTE rgbHash[16]; DWORD cbHash = 16; CHAR rgbDigits[] = "0123456789abcdef"; if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { return "CryptoContext Failed"; } if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { CryptReleaseContext(hProv, 0); return "CreateHash Failed"; } if (!CryptHashData(hHash, (BYTE*)serials.c_str(), (DWORD)serials.length(), 0)) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return "HashData Failed"; } if (!CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return "GetHashParam Failed"; } std::string hashStr; for (DWORD i = 0; i < cbHash; i++) { char rgb[3]; sprintf_s(rgb, 3, "%c%c", rgbDigits[rgbHash[i] >> 4], rgbDigits[rgbHash[i] & 0xf]); hashStr += rgb; } // 修正strcpy_s调用 strcpy_s(g_szMachineCode, sizeof(g_szMachineCode), hashStr.c_str()); return g_szMachineCode; } // 计算注册码函数 const char* ComputeRegistration(const char* machineCode, int daysChoice) { static char regBuffer[256] = { 0 }; std::string input = machineCode; std::string regCode; // 简单转换算法(实际应使用加密算法) for (char c : input) { regCode += (c + daysChoice) ^ 0xAA; } // 修正strcpy_s调用 strcpy_s(regBuffer, sizeof(regBuffer), regCode.c_str()); return regBuffer; } // 保存注册信息函数 BOOL SaveRegistration(const char* machineCode, const char* regCode, int daysChoice) { HKEY hKey; LPCSTR subKey = "Software\\MyApp\\Registration"; // 创建注册表项 if (RegCreateKeyExA(HKEY_CURRENT_USER, subKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { return FALSE; } // 保存机器码 RegSetValueExA(hKey, "MachineCode", 0, REG_SZ, (const BYTE*)machineCode, (DWORD)strlen(machineCode) + 1); // 保存注册码 RegSetValueExA(hKey, "RegCode", 0, REG_SZ, (const BYTE*)regCode, (DWORD)strlen(regCode) + 1); // 保存授权天数 DWORD days = 0; switch (daysChoice) { case 0: days = 7; break; case 1: days = 15; break; case 2: days = 30; break; case 3: days = 0xFFFFFFFF; // 永久 } RegSetValueExA(hKey, "Days", 0, REG_DWORD, (const BYTE*)&days, sizeof(days)); // 保存激活日期 SYSTEMTIME st; GetSystemTime(&st); FILETIME ft; SystemTimeToFileTime(&st, &ft); RegSetValueExA(hKey, "ActivationDate", 0, REG_QWORD, (const BYTE*)&ft, sizeof(ft)); RegCloseKey(hKey); return TRUE; } // 验证授权函数 int ValidateLicense() { HKEY hKey; LPCSTR subKey = "Software\\MyApp\\Registration"; if (RegOpenKeyExA(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) { return -1; // 未注册 } // 检查机器码是否匹配 char storedMachineCode[256] = { 0 }; DWORD size = sizeof(storedMachineCode); if (RegQueryValueExA(hKey, "MachineCode", NULL, NULL, (LPBYTE)storedMachineCode, &size) != ERROR_SUCCESS) { RegCloseKey(hKey); return -1; } if (strcmp(storedMachineCode, GetMachineCode()) != 0) { RegCloseKey(hKey); return -1; // 机器码不匹配 } // 检查授权天数 DWORD days = 0; size = sizeof(days); if (RegQueryValueExA(hKey, "Days", NULL, NULL, (LPBYTE)&days, &size) != ERROR_SUCCESS) { RegCloseKey(hKey); return -1; } // 永久授权 if (days == 0xFFFFFFFF) { RegCloseKey(hKey); return 1; } // 检查激活日期 FILETIME activationDate; size = sizeof(activationDate); if (RegQueryValueExA(hKey, "ActivationDate", NULL, NULL, (LPBYTE)&activationDate, &size) != ERROR_SUCCESS) { RegCloseKey(hKey); return -1; } // 计算已过天数 SYSTEMTIME stNow; FILETIME ftNow; GetSystemTime(&stNow); SystemTimeToFileTime(&stNow, &ftNow); ULARGE_INTEGER uAct, uNow; uAct.LowPart = activationDate.dwLowDateTime; uAct.HighPart = activationDate.dwHighDateTime; uNow.LowPart = ftNow.dwLowDateTime; uNow.HighPart = ftNow.dwHighDateTime; // 100纳秒 = 1 tick, 1天 = 864000000000 ticks ULONGLONG diff = (uNow.QuadPart - uAct.QuadPart) / 864000000000; RegCloseKey(hKey); return (diff <= days) ? 1 : 0; // 1=有效, 0=过期 } // 对话框消息处理 INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: g_hMainDlg = hDlg; InitializeControls(hDlg); ValidateLicenseOnStartup(); return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_GENERATE_BTN: GenerateRegistrationCode(hDlg); break; case IDC_REGISTER_BTN: RegisterProduct(hDlg); break; case IDC_VALIDATE_BTN: ValidateLicenseOnStartup(); break; case IDCANCEL: EndDialog(hDlg, 0); return TRUE; } break; } return FALSE; } // 初始化控件 void InitializeControls(HWND hDlg) { // 设置字体 HFONT hFont = CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial"); // 获取机器码并显示 const char* mc = GetMachineCode(); SetDlgItemTextA(hDlg, IDC_MACHINE_CODE, mc); // 设置控件字体 HWND hWnd = GetDlgItem(hDlg, IDC_MACHINE_CODE); SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE); hWnd = GetDlgItem(hDlg, IDC_REG_CODE); SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE); // 初始化授权天数下拉框 HWND hCombo = GetDlgItem(hDlg, IDC_DAYS_COMBO); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"7天试用"); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"15天试用"); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"30天正式版"); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"永久授权"); SendMessage(hCombo, CB_SETCURSEL, 3, 0); // 默认选择永久授权 // 设置状态文本 UpdateStatus("请选择授权类型并生成注册码"); } // 生成注册码 void GenerateRegistrationCode(HWND hDlg) { // 获取选择的授权天数 HWND hCombo = GetDlgItem(hDlg, IDC_DAYS_COMBO); int daysChoice = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0); // 计算注册码 const char* mc = GetMachineCode(); const char* regCode = ComputeRegistration(mc, daysChoice); // 显示注册码 SetDlgItemTextA(hDlg, IDC_REG_CODE, regCode); UpdateStatus("注册码已生成,点击注册按钮完成激活"); } // 注册产品 void RegisterProduct(HWND hDlg) { // 获取选择的授权天数 HWND hCombo = GetDlgItem(hDlg, IDC_DAYS_COMBO); int daysChoice = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0); // 获取注册码 char regCode[256] = { 0 }; GetDlgItemTextA(hDlg, IDC_REG_CODE, regCode, sizeof(regCode)); // 保存注册信息 const char* mc = GetMachineCode(); if (SaveRegistration(mc, regCode, daysChoice)) { UpdateStatus("产品注册成功!"); MessageBoxA(hDlg, "产品激活成功!", "注册成功", MB_OK | MB_ICONINFORMATION); } else { UpdateStatus("注册失败,请重试"); MessageBoxA(hDlg, "注册失败,请检查系统权限", "错误", MB_OK | MB_ICONERROR); } } // 验证授权 void ValidateLicenseOnStartup() { int status = ValidateLicense(); switch (status) { case 1: UpdateStatus("授权状态: 已激活 (有效授权)"); break; case 0: UpdateStatus("授权状态: 已过期 (请重新注册)"); break; case -1: UpdateStatus("授权状态: 未注册 (请激活产品)"); break; default: UpdateStatus("授权状态: 未知错误"); } } // 更新状态文本 void UpdateStatus(const char* message) { SetDlgItemTextA(g_hMainDlg, IDC_STATUS_TEXT, message); } // 主程序入口 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化COM if (FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { MessageBoxA(NULL, "COM初始化失败", "错误", MB_OK | MB_ICONERROR); return 1; } // 初始化通用控件 INITCOMMONCONTROLSEX icc; icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&icc); // 创建对话框 DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, DialogProc, 0); // 清理COM CoUninitialize(); return 0; } [NK201!无法解析的外部符号 main,函数 "int cdecl invoke main(void)"(?invoke main@@YAHXZ)中引用了该符号 LNK112(1 个无法解析的外部命令
最新发布
07-18
<think>我们注意到错误信息是:无法解析的外部符号 main。这是因为在Windows GUI程序中,入口点应该是WinMain,而不是main。但是,在代码中我们已经使用了WinMain作为入口点。然而,错误信息提到“无法解析的外部符号 main”,这可能是由于项目设置中子系统配置不正确导致的。 在Visual Studio中,我们需要将项目配置为使用“Windows (/SUBSYSTEM:WINDOWS)”子系统,而不是控制台子系统(/SUBSYSTEM:CONSOLE)。否则,链接器会期望找到main函数。 但是,我们也可以尝试在代码中显式指定入口点,以覆盖默认设置。在链接器选项中,我们可以设置入口点为WinMain。或者,我们可以在代码中通过链接指令来指定。 不过,我们也可以尝试另一种方法:在代码中加上以下指令,告诉链接器使用WinMain作为入口点。 ```cpp #pragma comment(linker, "/ENTRY:WinMain") ``` 但是注意,在Windows GUI程序中,入口点通常是WinMain,并且在使用DialogBoxParam等函数时,我们不需要main函数。 然而,错误信息中提到了“invoke main”,这可能是由于编译器设置的问题。让我们检查一下代码中是否有任何地方引用了main?实际上,我们并没有定义main函数,所以可能是项目设置的问题。 但是,为了确保代码的完整性,我们可以尝试以下方法: 1. 检查项目属性,确保子系统设置为Windows(/SUBSYSTEM:WINDOWS)。 2. 如果没有访问项目属性,可以在代码中通过指令设置。 我们可以添加以下指令: ```cpp #pragma comment(linker, "/SUBSYSTEM:WINDOWS") ``` 这样,链接器就会知道我们使用Windows子系统,并且不会寻找main函数。 因此,我们在代码开头(在包含头文件之后)添加: ```cpp #pragma comment(linker, "/SUBSYSTEM:WINDOWS") ``` 这样,链接器将使用Windows子系统,并且入口点将为WinMain(我们已经实现了WinMain)。 此外,我们还需要确保WinMain函数的签名正确。在代码中,WinMain的签名是: ```cpp int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) ``` 这是正确的。 现在,我们修改代码,添加链接器指令。 另外,我们注意到代码中有一个资源ID定义,但缺少了对话框资源的实际定义。在资源脚本(.rc)文件中,我们需要定义对话框资源。由于我们无法在代码中直接定义资源,这里假设资源脚本已经存在,并且包含了IDD_MAIN_DIALOG的定义。 但是,为了完整,我们可以提供一个简单的资源脚本内容(如果项目中没有的话,需要创建一个.rc文件并添加到项目中): 资源脚本(例如:app.rc): ``` #include <windows.h> IDD_MAIN_DIALOG DIALOGEX 0, 0, 300, 200 CAPTION "软件注册" FONT 9, "宋体" { LTEXT "机器码:",IDC_STATIC,20,20,40,14 EDITTEXT IDC_MACHINE_CODE,70,18,200,14,ES_AUTOHSCROLL | ES_READONLY LTEXT "授权天数:",IDC_STATIC,20,45,40,14 COMBOBOX IDC_DAYS_COMBO,70,43,100,100,CBS_DROPDOWNLIST LTEXT "注册码:",IDC_STATIC,20,70,40,14 EDITTEXT IDC_REG_CODE,70,68,200,14,ES_AUTOHSCROLL DEFPUSHBUTTON "生成注册码",IDC_GENERATE_BTN,70,95,80,14 PUSHBUTTON "注册",IDC_REGISTER_BTN,160,95,80,14 PUSHBUTTON "验证",IDC_VALIDATE_BTN,250,95,80,14 LTEXT "状态:",IDC_STATIC,20,120,40,14 LTEXT "",IDC_STATUS_TEXT,70,120,200,14 } ``` 注意:这个资源脚本只是示例,可能需要调整控件位置和大小。 由于我们无法在代码中包含资源脚本,因此在实际项目中,需要单独创建资源文件。 现在,我们修改代码,添加链接器指令,并确保入口点正确。 修改后的代码开头部分: ```cpp #include <Windows.h> #include <Wbemidl.h> #include <comdef.h> #include <WinCrypt.h> #include <string> #include <algorithm> #include <sstream> #include <vector> #include <commctrl.h> #include <iomanip> // 设置链接器选项:使用Windows子系统,入口点为WinMain #pragma comment(linker, "/SUBSYSTEM:WINDOWS") #pragma comment(linker, "/ENTRY:WinMain") // 显式指定入口点,但通常不需要,因为WinMain是标准入口点 // ... 其他代码保持不变 ... ``` 但是,请注意:在Windows编程中,入口点函数名称是WinMain,但链接器在Windows子系统中默认会查找WinMainCRTStartup,然后由C运行时库调用我们的WinMain。因此,通常我们不需要显式指定入口点为WinMain,因为编译器会为我们处理。所以,我们只设置子系统应该就够了。 所以,我们只保留: ```cpp #pragma comment(linker, "/SUBSYSTEM:WINDOWS") ``` 这样,链接器就不会去寻找main函数了。 另外,我们还需要注意,在代码中,我们使用了`DialogBoxParam`来创建对话框,因此需要确保资源文件被正确链接。 如果问题仍然存在,那么可能是资源文件没有被正确包含,或者链接器设置问题。 但是,由于问题描述是“无法解析的外部符号 main”,所以我们先解决这个问题。 修改后的代码: ```cpp // ... 头文件包含 ... // 设置链接器子系统为Windows,避免寻找main函数 #pragma comment(linker, "/SUBSYSTEM:WINDOWS") // 资源ID定义 #define IDD_MAIN_DIALOG 101 // ... 其他资源ID定义 ... // ... 后续代码不变 ... ``` 现在,重新编译应该可以解决main函数的问题。 如果还有其他链接错误,请根据错误信息调整。 由于我们无法实际编译,所以请根据实际环境调整。 注意:以上解决方案是在Visual Studio环境中的做法。如果使用其他编译器,设置可能不同。 最后,如果问题解决,程序应该能够正常运行。 如果还有问题,请提供具体的错误信息。 由于我们只收到了一个错误,所以先解决这个错误。 现在,我们给出修改后的完整代码(只添加了链接器指令,其他不变):</think>您的代码是一个Windows注册系统,但存在一个链接错误:无法解析的外部符号 `main`。这是因为在Windows GUI程序中,入口点应该是 `WinMain` 而不是 `main`。您的代码已经实现了 `WinMain`,但编译器/链接器设置可能存在问题。 ### 解决方案: 1. **检查项目设置**: - 在Visual Studio中,右键项目 → 属性 → 链接器 → 系统 → 子系统:设置为 **Windows (/SUBSYSTEM:WINDOWS)** - 入口点:留空或设置为 `WinMain` 2. **添加链接器指令**: 在代码开头添加以下指令强制使用Windows子系统: ```cpp // 添加在头文件之后 #pragma comment(linker, "/SUBSYSTEM:WINDOWS") ``` ### 修改后的完整代码: ```cpp #include <Windows.h> #include <Wbemidl.h> #include <comdef.h> #include <WinCrypt.h> #include <string> #include <algorithm> #include <sstream> #include <vector> #include <commctrl.h> #include <iomanip> // 添加链接器指令 #pragma comment(linker, "/SUBSYSTEM:WINDOWS") // 关键修复 #pragma comment(lib, "wbemuuid.lib") #pragma comment(lib, "Advapi32.lib") #pragma comment(lib, "Crypt32.lib") #pragma comment(lib, "comctl32.lib") // 资源ID定义 #define IDD_MAIN_DIALOG 101 #define IDC_MACHINE_CODE 1001 #define IDC_DAYS_COMBO 1002 #define IDC_REG_CODE 1003 #define IDC_GENERATE_BTN 1004 #define IDC_REGISTER_BTN 1005 #define IDC_STATUS_TEXT 1006 #define IDC_VALIDATE_BTN 1007 // 全局变量 HWND g_hMainDlg = NULL; char g_szMachineCode[256] = { 0 }; // 函数声明 const char* GetMachineCode(); const char* ComputeRegistration(const char* machineCode, int daysChoice); BOOL SaveRegistration(const char* machineCode, const char* regCode, int daysChoice); int ValidateLicense(); void UpdateStatus(const char* message); void InitializeControls(HWND hDlg); void GenerateRegistrationCode(HWND hDlg); void RegisterProduct(HWND hDlg); void ValidateLicenseOnStartup(); // 获取机器码函数 const char* GetMachineCode() { if (g_szMachineCode[0] != '\0') { return g_szMachineCode; } HRESULT hres; std::string serials; // 初始化COM hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return "COM Init Failed"; } // 设置COM安全级别 hres = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); if (FAILED(hres)) { CoUninitialize(); return "CoInitializeSecurity Failed"; } // 创建WMI实例 IWbemLocator* pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc ); if (FAILED(hres)) { CoUninitialize(); return "WbemLocator Failed"; } // 连接到WMI IWbemServices* pSvc = NULL; hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc ); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return "ConnectServer Failed"; } // 设置代理安全级别 hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return "SetProxyBlanket Failed"; } // 查询CPU信息 IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Processor"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator ); if (SUCCEEDED(hres)) { IWbemClassObject* pclsObj = NULL; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) break; VARIANT vtProp; hr = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { serials += _bstr_t(vtProp.bstrVal); VariantClear(&vtProp); } pclsObj->Release(); } pEnumerator->Release(); } // 查询磁盘信息 hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_DiskDrive"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator ); if (SUCCEEDED(hres)) { IWbemClassObject* pclsObj = NULL; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) break; VARIANT vtProp; hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { serials += _bstr_t(vtProp.bstrVal); VariantClear(&vtProp); } pclsObj->Release(); } pEnumerator->Release(); } // 清理资源 pSvc->Release(); pLoc->Release(); CoUninitialize(); // 生成哈希值 HCRYPTPROV hProv = 0; HCRYPTHASH hHash = 0; BYTE rgbHash[16]; DWORD cbHash = 16; CHAR rgbDigits[] = "0123456789abcdef"; if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { return "CryptoContext Failed"; } if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { CryptReleaseContext(hProv, 0); return "CreateHash Failed"; } if (!CryptHashData(hHash, (BYTE*)serials.c_str(), (DWORD)serials.length(), 0)) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return "HashData Failed"; } if (!CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) { CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return "GetHashParam Failed"; } std::string hashStr; for (DWORD i = 0; i < cbHash; i++) { char rgb[3]; sprintf_s(rgb, 3, "%c%c", rgbDigits[rgbHash[i] >> 4], rgbDigits[rgbHash[i] & 0xf]); hashStr += rgb; } strcpy_s(g_szMachineCode, sizeof(g_szMachineCode), hashStr.c_str()); return g_szMachineCode; } // 计算注册码函数 const char* ComputeRegistration(const char* machineCode, int daysChoice) { static char regBuffer[256] = { 0 }; std::string input = machineCode; std::string regCode; // 简单转换算法(实际应使用加密算法) for (char c : input) { regCode += (c + daysChoice) ^ 0xAA; } strcpy_s(regBuffer, sizeof(regBuffer), regCode.c_str()); return regBuffer; } // 保存注册信息函数 BOOL SaveRegistration(const char* machineCode, const char* regCode, int daysChoice) { HKEY hKey; LPCSTR subKey = "Software\\MyApp\\Registration"; // 创建注册表项 if (RegCreateKeyExA(HKEY_CURRENT_USER, subKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { return FALSE; } // 保存机器码 RegSetValueExA(hKey, "MachineCode", 0, REG_SZ, (const BYTE*)machineCode, (DWORD)strlen(machineCode) + 1); // 保存注册码 RegSetValueExA(hKey, "RegCode", 0, REG_SZ, (const BYTE*)regCode, (DWORD)strlen(regCode) + 1); // 保存授权天数 DWORD days = 0; switch (daysChoice) { case 0: days = 7; break; case 1: days = 15; break; case 2: days = 30; break; case 3: days = 0xFFFFFFFF; // 永久 } RegSetValueExA(hKey, "Days", 0, REG_DWORD, (const BYTE*)&days, sizeof(days)); // 保存激活日期 SYSTEMTIME st; GetSystemTime(&st); FILETIME ft; SystemTimeToFileTime(&st, &ft); RegSetValueExA(hKey, "ActivationDate", 0, REG_QWORD, (const BYTE*)&ft, sizeof(ft)); RegCloseKey(hKey); return TRUE; } // 验证授权函数 int ValidateLicense() { HKEY hKey; LPCSTR subKey = "Software\\MyApp\\Registration"; if (RegOpenKeyExA(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) { return -1; // 未注册 } // 检查机器码是否匹配 char storedMachineCode[256] = { 0 }; DWORD size = sizeof(storedMachineCode); if (RegQueryValueExA(hKey, "MachineCode", NULL, NULL, (LPBYTE)storedMachineCode, &size) != ERROR_SUCCESS) { RegCloseKey(hKey); return -1; } if (strcmp(storedMachineCode, GetMachineCode()) != 0) { RegCloseKey(hKey); return -1; // 机器码不匹配 } // 检查授权天数 DWORD days = 0; size = sizeof(days); if (RegQueryValueExA(hKey, "Days", NULL, NULL, (LPBYTE)&days, &size) != ERROR_SUCCESS) { RegCloseKey(hKey); return -1; } // 永久授权 if (days == 0xFFFFFFFF) { RegCloseKey(hKey); return 1; } // 检查激活日期 FILETIME activationDate; size = sizeof(activationDate); if (RegQueryValueExA(hKey, "ActivationDate", NULL, NULL, (LPBYTE)&activationDate, &size) != ERROR_SUCCESS) { RegCloseKey(hKey); return -1; } // 计算已过天数 SYSTEMTIME stNow; FILETIME ftNow; GetSystemTime(&stNow); SystemTimeToFileTime(&stNow, &ftNow); ULARGE_INTEGER uAct, uNow; uAct.LowPart = activationDate.dwLowDateTime; uAct.HighPart = activationDate.dwHighDateTime; uNow.LowPart = ftNow.dwLowDateTime; uNow.HighPart = ftNow.dwHighDateTime; // 100纳秒 = 1 tick, 1天 = 864000000000 ticks ULONGLONG diff = (uNow.QuadPart - uAct.QuadPart) / 864000000000; RegCloseKey(hKey); return (diff <= days) ? 1 : 0; // 1=有效, 0=过期 } // 对话框消息处理 INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: g_hMainDlg = hDlg; InitializeControls(hDlg); ValidateLicenseOnStartup(); return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_GENERATE_BTN: GenerateRegistrationCode(hDlg); break; case IDC_REGISTER_BTN: RegisterProduct(hDlg); break; case IDC_VALIDATE_BTN: ValidateLicenseOnStartup(); break; case IDCANCEL: EndDialog(hDlg, 0); return TRUE; } break; } return FALSE; } // 初始化控件 void InitializeControls(HWND hDlg) { // 设置字体 HFONT hFont = CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial"); // 获取机器码并显示 const char* mc = GetMachineCode(); SetDlgItemTextA(hDlg, IDC_MACHINE_CODE, mc); // 设置控件字体 HWND hWnd = GetDlgItem(hDlg, IDC_MACHINE_CODE); SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE); hWnd = GetDlgItem(hDlg, IDC_REG_CODE); SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE); // 初始化授权天数下拉框 HWND hCombo = GetDlgItem(hDlg, IDC_DAYS_COMBO); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"7天试用"); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"15天试用"); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"30天正式版"); SendMessageW(hCombo, CB_ADDSTRING, 0, (LPARAM)L"永久授权"); SendMessage(hCombo, CB_SETCURSEL, 3, 0); // 默认选择永久授权 // 设置状态文本 UpdateStatus("请选择授权类型并生成注册码"); } // 生成注册码 void GenerateRegistrationCode(HWND hDlg) { // 获取选择的授权天数 HWND hCombo = GetDlgItem(hDlg, IDC_DAYS_COMBO); int daysChoice = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0); // 计算注册码 const char* mc = GetMachineCode(); const char* regCode = ComputeRegistration(mc, daysChoice); // 显示注册码 SetDlgItemTextA(hDlg, IDC_REG_CODE, regCode); UpdateStatus("注册码已生成,点击注册按钮完成激活"); } // 注册产品 void RegisterProduct(HWND hDlg) { // 获取选择的授权天数 HWND hCombo = GetDlgItem(hDlg, IDC_DAYS_COMBO); int daysChoice = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0); // 获取注册码 char regCode[256] = { 0 }; GetDlgItemTextA(hDlg, IDC_REG_CODE, regCode, sizeof(regCode)); // 保存注册信息 const char* mc = GetMachineCode(); if (SaveRegistration(mc, regCode, daysChoice)) { UpdateStatus("产品注册成功!"); MessageBoxA(hDlg, "产品激活成功!", "注册成功", MB_OK | MB_ICONINFORMATION); } else { UpdateStatus("注册失败,请重试"); MessageBoxA(hDlg, "注册失败,请检查系统权限", "错误", MB_OK | MB_ICONERROR); } } // 验证授权 void ValidateLicenseOnStartup() { int status = ValidateLicense(); switch (status) { case 1: UpdateStatus("授权状态: 已激活 (有效授权)"); break; case 0: UpdateStatus("授权状态: 已过期 (请重新注册)"); break; case -1: UpdateStatus("授权状态: 未注册 (请激活产品)"); break; default: UpdateStatus("授权状态: 未知错误"); } } // 更新状态文本 void UpdateStatus(const char* message) { SetDlgItemTextA(g_hMainDlg, IDC_STATUS_TEXT, message); } // 主程序入口 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 初始化COM if (FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { MessageBoxA(NULL, "COM初始化失败", "错误", MB_OK | MB_ICONERROR); return 1; } // 初始化通用控件 INITCOMMONCONTROLSEX icc; icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&icc); // 创建对话框 DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, DialogProc, 0); // 清理COM CoUninitialize(); return 0; } ``` ### 关键修改说明: 1. **添加链接器指令**: ```cpp #pragma comment(linker, "/SUBSYSTEM:WINDOWS") ``` 这行代码告诉链接器使用Windows子系统,避免寻找`main`函数。 2. **入口点确认**: 确保程序入口点是`WinMain`而不是`main`,您的代码已正确实现。 3. **资源文件**: 需要创建对应的`.rc`资源文件定义`IDD_MAIN_DIALOG`对话框资源。 ### 相关问题: 1. 为什么Windows GUI程序需要特殊的子系统设置? 2. 如何创建和编译Windows资源文件(.rc)? 3. 在注册系统中,如何增强注册码的加密安全性? 4. 如何处理用户修改系统时间绕过授权检查的问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值