void RemoveWindowFromStack(HWND hwnd) { HWNDStackNode *current = hwnd_stack_top, *prev = 0; while(current) { if (current->hwnd == hwnd) { if (prev) prev->next = current->next; else hwnd_stack_top = current->next; mir_free(current); stack_size--; break; } prev = current; current = current->next; } // Если после удаления в стеке остались окна, то нужно провести сжатие: // сдвинуть все окна к верхнему/нижнему краю экрана. if (hwnd_stack_top) RepositionWindows(); }
void AddWindowToStack(HWND hwnd) { HWNDStackNode *new_node = (HWNDStackNode *)mir_alloc(sizeof(HWNDStackNode)); new_node->hwnd = hwnd; new_node->next = hwnd_stack_top; hwnd_stack_top = new_node; int height; SendMessage(hwnd, PUM_GETHEIGHT, (WPARAM)&height, 0); RECT wa_rect; SystemParametersInfo(SPI_GETWORKAREA, 0, &wa_rect, 0); if (options.use_mim_monitor) { RECT clr; GetWindowRect(pcli->hwndContactList, &clr); HMONITOR hMonitor = MonitorFromRect(&clr, MONITOR_DEFAULTTONEAREST); if (hMonitor) { MONITORINFO mi; mi.cbSize = sizeof(mi); if (GetMonitorInfo(hMonitor, &mi)) wa_rect = mi.rcWork; } } switch (options.animate) { case ANIMATE_NO: if (options.location == PL_BOTTOMRIGHT || options.location == PL_TOPRIGHT) pop_start_x = wa_rect.right - options.win_width - 1; else pop_start_x = wa_rect.left + 1; if (options.location == PL_BOTTOMRIGHT || options.location == PL_BOTTOMLEFT) pop_start_y = wa_rect.bottom; else pop_start_y = wa_rect.top + 1; break; case ANIMATE_HORZ: if (options.location == PL_BOTTOMRIGHT || options.location == PL_TOPRIGHT) pop_start_x = wa_rect.right; else pop_start_x = wa_rect.left - options.win_width; if (options.location == PL_BOTTOMRIGHT || options.location == PL_BOTTOMLEFT) pop_start_y = wa_rect.bottom; else pop_start_y = wa_rect.top + 1; break; case ANIMATE_VERT: if (options.location == PL_BOTTOMRIGHT || options.location == PL_TOPRIGHT) pop_start_x = wa_rect.right - options.win_width - 1; else pop_start_x = wa_rect.left + 1; if (options.location == PL_BOTTOMRIGHT || options.location == PL_BOTTOMLEFT) pop_start_y = wa_rect.bottom; else pop_start_y = wa_rect.top - height + 1; break; } SetWindowPos(hwnd, 0, pop_start_x, pop_start_y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); stack_size++; RepositionWindows(); }
unsigned __stdcall MessagePumpThread(void* param) { if (param) SetEvent((HANDLE)param); MSG hwndMsg = { 0 }; while (GetMessage(&hwndMsg, 0, 0, 0) > 0 && !bShutdown) { if (hwndMsg.hwnd != NULL && IsDialogMessage(hwndMsg.hwnd, &hwndMsg)) /* Wine fix. */ continue; switch(hwndMsg.message) { case MUM_CREATEPOPUP: { bool enabled = true; int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0); if (status >= ID_STATUS_OFFLINE && status <= ID_STATUS_OUTTOLUNCH && options.disable_status[status - ID_STATUS_OFFLINE]) enabled = false; if ((options.disable_full_screen && IsFullScreen()) || IsWorkstationLocked()) enabled = false; PopupData *pd = (PopupData*)hwndMsg.lParam; if (enabled && num_popups < MAX_POPUPS) { //HWND hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, POP_WIN_CLASS, _T("Popup"), WS_POPUP, 0, 0, 0, 0, GetDesktopWindow(), 0, hInst, (LPVOID)hwndMsg.lParam); HWND hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, POP_WIN_CLASS, _T("Popup"), WS_POPUP, 0, 0, 0, 0, 0, 0, hInst, (LPVOID)hwndMsg.lParam); num_popups++; if (hwndMsg.wParam) // set notifyer handle SendMessage(hwnd, PUM_SETNOTIFYH, hwndMsg.wParam, 0); } else if (pd) { mir_free(pd->pwzTitle); mir_free(pd->pwzText); mir_free(pd); } } break; case MUM_DELETEPOPUP: { HWND hwnd = (HWND)hwndMsg.lParam; if (IsWindow(hwnd)) { DestroyWindow(hwnd); num_popups--; } } break; case MUM_NMUPDATE: BroadcastMessage(PUM_UPDATENOTIFY, hwndMsg.wParam, 0); break; case MUM_NMREMOVE: BroadcastMessage(PUM_KILLNOTIFY, hwndMsg.wParam, 0); break; case MUM_NMAVATAR: RepositionWindows(); break; default: TranslateMessage(&hwndMsg); DispatchMessage(&hwndMsg); break; } } DeinitWindowStack(); num_popups = 0; return 0; }