获取程序实例:hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;

本文详细解释了lParam在操作系统调用窗口过程时传递给应用程序的参数意义,特别关注WM_CREATE消息场景下lParam如何保存指向LPCREATESTRUCT结构的地址,并解析如何从中获取hInstance实例句柄。
lParam是操作系统调用你的窗口过程传给你的参数 他根据处理消息的不同含义也会不同

当在处理WM_CREATE消息时 lParam里面保存的是一指针,指向LPCREATESTRUCT结构的地址。

((LPCREATESTRUCT) lParam)->hInstance 就是通过保存在lParam里面的地址取出LPCREATESTRUCT结构里面的hInstance 即程序的实例句柄 

#include <Windows.h> #include <sstream> // 定义单循环链表节点结构 struct Node { int data; Node* next; Node(int value) : data(value), next(NULL) {} }; // 创建单循环链表 Node* createCircularList(int n) { Node* head = new Node(1); Node* current = head; for (int i = 2; i <= n; ++i) { current->next = new Node(i); current = current->next; } current->next = head; // 使链表成为循环链表 return head; } // 猴子选大王算法(单循环链表实现) std::string monkeyKingSelection(int n, int m) { if (n <= 0 || m <= 0) return ""; Node* head = createCircularList(n); Node* prev = NULL; Node* current = head; std::string result; while (current->next != current) { for (int i = 1; i < m; ++i) { prev = current; current = current->next; } std::ostringstream oss; oss << current->data; result += oss.str() + " "; // 删除当前节点 if (prev) { prev->next = current->next; } else { // 如果prev为空,说明要删除的是头节点 Node* temp = current; while (temp->next != current) { temp = temp->next; } temp->next = current->next; // 更新尾节点的next指向新的头节点 head = current->next; // 更新头节点 } Node* toDelete = current; current = current->next; delete toDelete; } std::ostringstream oss; oss << current->data; result += oss.str(); delete current; return result; } // 窗口过程函数 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HWND hEdit1, hEdit2, hButton, hOutput; static HWND hLabel1, hLabel2; switch (msg) { case WM_CREATE: // 创建第一个标签 hLabel1 = CreateWindow("STATIC", "个数:", WS_CHILD | WS_VISIBLE, 10, 10, 50, 20, hwnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第一个文本框 hEdit1 = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 60, 10, 100, 20, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第二个标签 hLabel2 = CreateWindow("STATIC", "步数:", WS_CHILD | WS_VISIBLE, 10, 40, 50, 20, hwnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第二个文本框 hEdit2 = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 60, 40, 100, 20, hwnd, (HMENU)2, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建确定按钮 hButton = CreateWindow("BUTTON", "确定", WS_CHILD | WS_VISIBLE, 10, 70, 80, 30, hwnd, (HMENU)3, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建输出文本框 hOutput = CreateWindow("STATIC", "", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 110, 250, 50, hwnd, (HMENU)4, ((LPCREATESTRUCT)lParam)->hInstance, NULL); break; case WM_COMMAND: if (LOWORD(wParam) == 3) { // 点击确定按钮 char buffer1[256], buffer2[256]; GetWindowText(hEdit1, buffer1, sizeof(buffer1)); GetWindowText(hEdit2, buffer2, sizeof(buffer2)); int n = atoi(buffer1); int m = atoi(buffer2); std::string result = monkeyKingSelection(n, m); SetWindowTextA(hOutput, result.c_str()); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } // 主函数,窗体程序的进入点 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = {}; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.lpszClassName = "MyWindowClass"; RegisterClass(&wc); // 创建窗口 HWND hwnd = CreateWindow(wc.lpszClassName, "猴子选大王问题", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, hInstance, NULL); // 显示窗口 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 消息循环 MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } 阐述项目分析的过程、解决问题的思路(必要时可加入图表)和建模所用的数据结构,给出具体的数据类型定义及相关注释说明、各模块的函数声明及功能说明。
11-15
#include <Windows.h> #include <sstream> #include <vector> // 猴子选大王算法 std::string monkeyKingSelection(int n, int m) { std::vector<int> monkeys; for (int i = 1; i <= n; ++i) { monkeys.push_back(i); } std::string result; int index = 0; while (!monkeys.empty()) { index = (index + m - 1) % monkeys.size(); std::ostringstream oss; oss << monkeys[index]; result += oss.str() + " "; monkeys.erase(monkeys.begin() + index); } return result; } // 窗口过程函数 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HWND hEdit1, hEdit2, hButton, hOutput; static HWND hLabel1, hLabel2; switch (msg) { case WM_CREATE: // 创建第一个标签 hLabel1 = CreateWindow("STATIC", "个数:", WS_CHILD | WS_VISIBLE, 10, 10, 50, 20, hwnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第一个文本框 hEdit1 = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 60, 10, 100, 20, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第二个标签 hLabel2 = CreateWindow("STATIC", "步数:", WS_CHILD | WS_VISIBLE, 10, 40, 50, 20, hwnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第二个文本框 hEdit2 = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 60, 40, 100, 20, hwnd, (HMENU)2, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建确定按钮 hButton = CreateWindow("BUTTON", "确定", WS_CHILD | WS_VISIBLE, 10, 70, 80, 30, hwnd, (HMENU)3, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建输出文本框 hOutput = CreateWindow("STATIC", "", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 110, 250, 50, hwnd, (HMENU)4, ((LPCREATESTRUCT)lParam)->hInstance, NULL); break; case WM_COMMAND: if (LOWORD(wParam) == 3) { // 点击确定按钮 char buffer1[256], buffer2[256]; GetWindowText(hEdit1, buffer1, sizeof(buffer1)); GetWindowText(hEdit2, buffer2, sizeof(buffer2)); int n = atoi(buffer1); int m = atoi(buffer2); std::string result = monkeyKingSelection(n, m); SetWindowTextA(hOutput, result.c_str()); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } // 主函数,窗体程序的进入点 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = {}; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.lpszClassName = "MyWindowClass"; RegisterClass(&wc); // 创建窗口 HWND hwnd = CreateWindow(wc.lpszClassName, "My Window with Two Text Boxes and Button", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, hInstance, NULL); // 显示窗口 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 消息循环 MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } 算法要求用单循环链表
11-15
#include <Windows.h> // 包含 Windows API 相关函数和数据结构的头文件 #include <sstream> // 包含字符串流操作的头文件,用于数字与字符串的转换 // 定义单循环链表节点结构,包含数据域和指向下一个节点的指针 struct Node { int data; // 节点存储的数据 Node* next; // 指向下一个节点的指针 Node(int value) : data(value), next(NULL) {} // 构造函数,初始化数据和指针 }; // 创建单循环链表,参数为链表中节点的数量 Node* createCircularList(int n) { if (n <= 0) return NULL; // 如果节点数小于等于0,返回空指针 Node* head = new Node(1); // 创建头节点,数据为1 Node* current = head; // 当前节点指针,用于遍历链表 // 循环创建剩余节点,并将它们连接起来 for (int i = 2; i <= n; ++i) { current->next = new Node(i); // 创建新节点,并将当前节点的next指针指向它 current = current->next; // 移动当前节点指针到新创建的节点 } // 将链表尾部的next指针指向头节点,形成循环 current->next = head; return head; // 返回链表头节点 } // 猴子选大王算法,参数分别为猴子数量和报数步长,返回选中猴子的顺序 std::string monkeyKingSelection(int n, int m) { if (n <= 0 || m <= 0) return ""; // 如果输入参数非法,返回空字符串 Node* head = createCircularList(n); // 根据猴子数量创建循环链表 if (!head) return ""; // 如果链表创建失败,返回空字符串 Node* prev = NULL; // 用于记录当前节点的前驱节点 Node* current = head; // 当前节点指针,初始化为头节点 std::string result; // 用于存储选中猴子的顺序结果 // 循环直到只剩一个节点(即选中大王) while (current->next != current) { // 移动current指针m-1次,找到要淘汰的猴子(因为从当前节点开始算数) for (int i = 1; i < m; ++i) { prev = current; // 记录前驱节点 current = current->next; // 移动到下一个节点 } // 将当前节点的值添加到结果字符串中 std::ostringstream oss; oss << current->data; // 将节点数据转换为字符串 result += oss.str() + " "; // 追加到结果字符串,并添加空格分隔 // 删除当前节点 if (prev) { prev->next = current->next; // 前驱节点的next指针跳过当前节点,直接指向下一个节点 } else { // 如果prev为空,说明要删除的是头节点,需要特殊处理 Node* temp = current; // 找到链表中最后一个节点(即当前节点的前一个节点) while (temp->next != current) { temp = temp->next; } temp->next = current->next; // 最后一个节点的next指针指向新的头节点 head = current->next; // 更新头节点为下一个节点 } Node* toDelete = current; // 保存当前要删除的节点 current = current->next; // 移动current指针到下一个节点 delete toDelete; // 删除旧的当前节点 } // 将最后一个剩下的节点(即大王)的数据添加到结果字符串 std::ostringstream oss; oss << current->data; result += oss.str(); delete current; // 删除最后一个节点,释放内存 return result; // 返回选中猴子的顺序 } // 窗口过程函数,处理窗口的各种消息 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { // 静态变量用于存储窗口控件的句柄,防止在多次消息处理中重复创建 static HWND hEdit1, hEdit2, hButton, hOutput; static HWND hLabel1, hLabel2; switch (msg) { case WM_CREATE: // 窗口创建消息,用于初始化窗口控件 // 创建第一个标签,显示“个数:”文本,用于提示用户输入猴子数量 hLabel1 = CreateWindow("STATIC", "个数:", WS_CHILD | WS_VISIBLE, // 窗口样式:子窗口、可见 10, 10, 50, 20, // 位置和大小 hwnd, NULL, // 父窗口和菜单项ID ((LPCREATESTRUCT)lParam)->hInstance, // 实例句柄 NULL); // 创建参数,这里为NULL // 创建第一个文本框,用于输入猴子数量 hEdit1 = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 60, 10, 100, 20, hwnd, (HMENU)1, // 菜单项ID为1,用于区分控件 ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第二个标签,显示“步数:”文本,用于提示用户输入报数步长 hLabel2 = CreateWindow("STATIC", "步数:", WS_CHILD | WS_VISIBLE, 10, 40, 50, 20, hwnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建第二个文本框,用于输入报数步长 hEdit2 = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT, 60, 40, 100, 20, hwnd, (HMENU)2, // 菜单项ID为2 ((LPCREATESTRUCT)lParam)->hInstance, NULL); // 创建确定按钮,用于触发猴子选大王算法的执行 hButton = CreateWindow("BUTTON", "确定", WS_CHILD | WS_VISIBLE, 10, 70, 80, 30, hwnd, (HMENU)3, // 菜单项ID为3 像这样类似创作一个窗体关于基于邻接表的长度为k的简单路径的求解图知识点的窗体
12-12
// 窗口过程函数:处理Windows消息,核心是WM_DEVICECHANGE LRESULT CALLBACK HIDDeviceManager::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DEVICECHANGE: { PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam; if (pHdr == nullptr) { break; } // 设备插入/移除事件,且类型为设备接口 if ((wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) && pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { // 设备路径 PDEV_BROADCAST_DEVICEINTERFACE pDevInterface = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr; std::string devicePath = ToolClass::wchar_tTostring(pDevInterface->dbcc_name); auto hidDevice = HIDDeviceManager::getInstance(); hidDevice->updateCurDeviceSet(); if (devicePath == hidDevice->getCurConnectedDevice().devicePath) { hidDevice->closeDevice(); } } break; } case WM_INPUT: { auto* pThis = reinterpret_cast<HIDDeviceManager*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); if (pThis) { pThis->processRawInput(reinterpret_cast<HRAWINPUT>(lParam)); } return 0; } case WM_CREATE: { LPCREATESTRUCT pCreate = reinterpret_cast<LPCREATESTRUCT>(lParam); SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreate->lpCreateParams)); OutputDebugString(L"窗口创建成功\n"); return 0; } case WM_DESTROY: // 窗口销毁时发送退出消息,结束消息循环 PostQuitMessage(0); break; default: // 未处理的消息交给系统默认处理 return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } devDef::DeviceHashSet HIDDeviceManager::getLastPcDeviceSet() { //// 获取HID设备的设备接口类GUID //GUID hidGuid; //HidD_GetHidGuid(&hidGuid); // 获取HID类设备信息集 HDEVINFO deviceInfoSet = SetupDiGetClassDevs( &GUID_DEVINTERFACE_HID, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); if (deviceInfoSet == INVALID_HANDLE_VALUE) { Logger::getInstance()->debug("获取HID设备信息失败,错误码:%1" + std::to_string(GetLastError())); return {}; } SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 }; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // 枚举所有HID设备 devDef::DeviceHashSet deviceSet = {}; for (DWORD i = 0; SetupDiEnumDeviceInterfaces(deviceInfoSet, nullptr, &GUID_DEVINTERFACE_HID, i, &deviceInterfaceData); i++) { // 获取设备路径长度 DWORD requiredSize = 0; SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, nullptr, 0, &requiredSize, nullptr); // 分配内存并获取设备路径 PSP_DEVICE_INTERFACE_DETAIL_DATA_W deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)LocalAlloc(LPTR, requiredSize); if (deviceInterfaceDetailData == nullptr) { SetupDiDestroyDeviceInfoList(deviceInfoSet); continue; } deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); // 关键:需要SP_DEVINFO_DATA来读取注册表属性 SP_DEVINFO_DATA devInfoData = { 0 }; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); // 获取完整的设备接口详情 if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, nullptr, &devInfoData)) { LocalFree(deviceInterfaceDetailData); continue; } // 打开设备以获取详细信息 HANDLE deviceHandle = CreateFile( deviceInterfaceDetailData->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr ); if (deviceHandle == INVALID_HANDLE_VALUE) { LocalFree(deviceInterfaceDetailData); continue; } // 获取设备属性 HIDD_ATTRIBUTES attributes = { 0 }; attributes.Size = sizeof(HIDD_ATTRIBUTES); if (!HidD_GetAttributes(deviceHandle, &attributes)) { CloseHandle(deviceHandle); LocalFree(deviceInterfaceDetailData); continue; } // 获取Usage和UsagePage PHIDP_PREPARSED_DATA preparsedData; if (!HidD_GetPreparsedData(deviceHandle, &preparsedData)) { CloseHandle(deviceHandle); LocalFree(deviceInterfaceDetailData); continue; } HIDP_CAPS capabilities; if (!HidP_GetCaps(preparsedData, &capabilities)) { HidD_FreePreparsedData(preparsedData); CloseHandle(deviceHandle); LocalFree(deviceInterfaceDetailData); continue; } HidD_FreePreparsedData(preparsedData); devDef::InfoDevice hidDevice; hidDevice.vendorId = attributes.VendorID; hidDevice.productId = attributes.ProductID; hidDevice.usagePage = capabilities.UsagePage; hidDevice.usage = capabilities.Usage; hidDevice.deviceType = getDeviceType(attributes.VendorID, attributes.ProductID); if (h_supportDeviceSet.find(hidDevice) == h_supportDeviceSet.end()) { CloseHandle(deviceHandle); LocalFree(deviceInterfaceDetailData); continue; } // 获取产品字符串 wchar_t product[256] = { 0 }; if (HidD_GetProductString(deviceHandle, product, sizeof(product))) { hidDevice.description = ToolClass::wchar_tTostring(product); } hidDevice.devicePath = ToolClass::wchar_tTostring(deviceInterfaceDetailData->DevicePath); deviceSet.insert(std::move(hidDevice)); CloseHandle(deviceHandle); LocalFree(deviceInterfaceDetailData); } SetupDiDestroyDeviceInfoList(deviceInfoSet); return deviceSet; } 如何辨别getLastPcDeviceSet和WndProc的WM_INPUT事件中获取到的端口,对应的物理设备是否是同一个
最新发布
12-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值