他来了,他来了,桌面图标一百种玩法第三种,桌面时钟。
学会了就发给女朋侪玩吧,效果炫酷,学不了亏损,学不了上当,走过途经不要错过。
老例子,先看看视频效果。
C++用桌面图标系列之三【整理-时钟】
焦点代码
除了根本的时间展示之外,还包罗了初始动画。
- int nScreenWith;int nScreenHeigh;typedef struct tagMovingIcon{ int index; int targetX; int targetY; int startX; int startY; int aniDelay; //动画延迟时间,随机的。打造一种乱中有序的氛围}MovingIcon, *PMovingIcon;vector vMoveAniIcons; //动画队列的图标索引ULONGLONG startAniTick; //记载动画起始时间DWORD dwProcessId = 0;HANDLE hProcess;LPVOID lpvPt;BOOL MoveTo(int numIndex, int posX, int posY, int iconIndex, bool moveAni = false);void WriteNumber(int numIndex, int numberShade[ROW][COL], bool moveAni = false);BOOL CALLBACK EnumWindowsProc(_In_ HWND TopHandle, _In_ LPARAM topparamhandle);void DoMoveAni();//桌面图标层句柄HWND hwndSysListView32;//逻辑起点void ClockLogic(){ vector vNumberShade; vNumberShade.push_back(num0); vNumberShade.push_back(num1); vNumberShade.push_back(num2); vNumberShade.push_back(num3); vNumberShade.push_back(num4); vNumberShade.push_back(num5); vNumberShade.push_back(num6); vNumberShade.push_back(num7); vNumberShade.push_back(num8); vNumberShade.push_back(num9); HWND hwndParent = ::FindWindow("Progman", "Program Manager"); HWND hwndSHELLDLL_DefView = ::FindWindowEx(hwndParent, NULL, "SHELLDLL_DefView", NULL); hwndSysListView32 = ::FindWindowEx(hwndSHELLDLL_DefView, NULL, "SysListView32", "FolderView"); if (hwndSysListView32 == NULL) { //***注意,某些情句柄有空的,实验用下面的函数来查找句柄*** //***也可以自行使用vs的工具spy++工具来检察层级是否准确***** EnumWindows(EnumWindowsProc, (LPARAM)nullptr); if (hwndSysListView32 == NULL) return; } int iconCount = ListView_GetItemCount(hwndSysListView32); if (iconCount < TOTAL_ICON_COUNT) { //图标数量不敷啊大佬,多复制几个 return; } GetWindowThreadProcessId(hwndSysListView32, &dwProcessId); //通过桌面窗口句柄获取此窗口所在进程的PID,实在就是explorer进程 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); //打开指定PID进程,取得进程句柄 lpvPt = VirtualAllocEx(hProcess, NULL, sizeof(POINT), MEM_COMMIT, PAGE_READWRITE);//在指定进程内里申请一个POINI布局巨细的空间. for (size_t i = 0; i < iconCount; i++) { if (i >= TOTAL_ICON_COUNT - 1) { //这里会将所有多余的桌面图标放到接们看不见的位置,反面可以右键桌面设置对齐网格还原图标位置 SendMessage(hwndSysListView32, LVM_SETITEMPOSITION, i, MAKELPARAM(-100, -100)); } else { //将图标打乱,这部门只是为了拍视频 可删除 random_device rd; uniform_int_distribution ranX(0, nScreenWith); uniform_int_distribution ranY(0, nScreenHeigh); SendMessage(hwndSysListView32, LVM_SETITEMPOSITION, i, MAKELPARAM(ranX(rd), ranY(rd))); } } //这部门只是为了拍视频 可删除 Sleep(3000); time_t currentTime; struct tm* p; ULONGLONG nextClockTick = GetTickCount64() + ANI_TOTAL_TIME + ANI_DELAY_TIME;//加上动画需要的时间,动画阶数再开始显示时间 ULONGLONG nextAniTick = GetTickCount64(); startAniTick = GetTickCount64(); int checkHour = -1; int checkMin = -1; while (1) { if (GetTickCount64() >= nextAniTick) { time(¤tTime); p = localtime(¤tTime); if (vMoveAniIcons.size() tm_hour / 10; int hour2 = p->tm_hour % 10; WriteNumber(0, vNumberShade[hour1], true); WriteNumber(1, vNumberShade[hour2], true); int min1 = p->tm_min / 10; int min2 = p->tm_min % 10; WriteNumber(2, vNumberShade[min1], true); WriteNumber(3, vNumberShade[min2], true); int sec1 = p->tm_sec / 10; int sec2 = p->tm_sec % 10; WriteNumber(4, vNumberShade[sec1], true); WriteNumber(5, vNumberShade[sec2], true); } DoMoveAni(); nextAniTick += 10;//移动隔断 } //下面是正式的时钟显示逻辑/// if (GetTickCount64() < nextClockTick) continue; nextClockTick = GetTickCount64() + 1000; time(¤tTime); p = localtime(¤tTime); //小时 if (checkHour == -1 || checkHour != p->tm_hour) { checkHour = p->tm_hour; int hour1 = p->tm_hour / 10;//十位数 int hour2 = p->tm_hour % 10;//个位数 WriteNumber(0, vNumberShade[hour1]); WriteNumber(1, vNumberShade[hour2]); } //分钟 if (checkMin == -1 || checkMin != p->tm_min) { checkMin = p->tm_min; int min1 = p->tm_min / 10; int min2 = p->tm_min % 10; WriteNumber(2, vNumberShade[min1]); WriteNumber(3, vNumberShade[min2]); } //秒的 int sec1 = p->tm_sec / 10; int sec2 = p->tm_sec % 10; WriteNumber(4, vNumberShade[sec1]); WriteNumber(5, vNumberShade[sec2]); }}void WriteNumber(int numIndex, int numberShade[ROW][COL], bool moveAni){ int nIconIndex = numIndex * (ROW * COL); for (size_t row = 0; row < ROW; row++) { for (size_t col = 0; col < COL; col++) { if (numberShade[row][col] == 1) MoveTo(numIndex, row, col, nIconIndex, moveAni); else MoveTo(numIndex, -1, -1, nIconIndex, moveAni); //不需要显示的就挪到看不见的地方 ++nIconIndex; } }}//图标iconIndex 移动到目标点BOOL MoveTo(int numIndex, int row, int col, int iconIndex, bool moveAni){ //int numGap = numIndex % 2 == 0 ? (numIndex / 2) * NUM_GAP2 : ((numIndex - 1) / 2) * NUM_GAP2 + NUM_GAP1;// int targetX = 0, targetY = 0, numGap = 0; if (row == -1)//需要移出屏幕的图标 { targetX = -100; targetY = 0; } else if (numIndex == 0 || numIndex == 1)//时 { numGap = numIndex % 2 == 0 ? 0 : NUM_GAP1; targetX = nScreenWith / 4 - GRID_WIDTH * COL + numGap + col * GRID_WIDTH; targetY = nScreenHeigh / 3 + row * GRID_WIDTH - 120; } else if (numIndex == 2 || numIndex == 3)//分 { numGap = numIndex % 2 == 0 ? 0 : NUM_GAP1; targetX = (3 * nScreenWith / 4) - GRID_WIDTH * COL + numGap + col * GRID_WIDTH; targetY = nScreenHeigh / 3 + row * GRID_WIDTH - 120; } else if (numIndex == 4 || numIndex == 5)//秒 { numGap = numIndex % 2 == 0 ? 0 : NUM_GAP1; targetX = nScreenWith / 2 - GRID_WIDTH * COL + numGap + col * GRID_WIDTH; targetY = nScreenHeigh / 2 + row * GRID_WIDTH + 30; } //需要播放动画的 if (moveAni && row != -1) { //获取图标初始位置 POINT pIconCurPos; ListView_GetItemPosition(hwndSysListView32, iconIndex, lpvPt); ReadProcessMemory(hProcess, lpvPt, &pIconCurPos, sizeof(POINT), NULL); random_device rd; //取0 - ANI_DELAY_TIME的随机数 uniform_int_distribution dist(0, ANI_DELAY_TIME); MovingIcon icon; icon.index = iconIndex; icon.targetX = targetX; icon.targetY = targetY; icon.startX = pIconCurPos.x; icon.startY = pIconCurPos.y; icon.aniDelay = dist(rd); //放到动画队列里 vMoveAniIcons.push_back(icon); } else { SendMessage(hwndSysListView32, LVM_SETITEMPOSITION, iconIndex, MAKELPARAM(targetX, targetY)); } return true;}//做初始动画void DoMoveAni(){ //动画做了多久 ULONGLONG nPassedTime = GetTickCount64() - startAniTick; if (nPassedTime > ANI_TOTAL_TIME + ANI_DELAY_TIME) return; for (auto iter = vMoveAniIcons.begin(); iter != vMoveAniIcons.end(); ++iter) { if (nPassedTime < iter->aniDelay) continue; if (nPassedTime - iter->aniDelay >= ANI_TOTAL_TIME) { //校正最后的位置 SendMessage(hwndSysListView32, LVM_SETITEMPOSITION, iter->index, MAKELPARAM(iter->targetX, iter->targetY)); continue; } //当前所在位置 = (颠末的时间 / 总时间) * (总旅程) //按时间比例来算,应该不复杂 = =! int targetX = 0, targetY = 0; targetX = ((double)(nPassedTime - iter->aniDelay) / (ANI_TOTAL_TIME)) * (iter->targetX - iter->startX); targetY = ((double)(nPassedTime - iter->aniDelay) / (ANI_TOTAL_TIME)) * (iter->targetY - iter->startY); //在vs的输出界面打印信息 char out0[128] = { 0 }; sprintf(out0, "index=%d x=%d y=%d \n", iter->index, targetX, targetY); //OutputDebugStringA(out0); targetX += iter->startX; targetY += iter->startY; SendMessage(hwndSysListView32, LVM_SETITEMPOSITION, iter->index, MAKELPARAM(targetX, targetY)); }}
复制代码 这里是完整代码和可执行文件。
https://download.csdn.net/download/Yang9325/13999888
来源:https://blog.csdn.net/Yang9325/article/details/112056356
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |