xoblite™ / Blackbox for Windows bb5 | RC6 preview | 0.25.2.14
http://xoblite.net/
Desktop Class Reference

#include <Desktop.h>

Classes

struct  WallpaperStruct
 

Public Types

typedef struct Desktop::WallpaperStruct WallpaperStruct
 

Public Member Functions

 Desktop (HINSTANCE hInstance)
 
 ~Desktop ()
 
void UpdateDesktopWindow ()
 
void GetDimensions ()
 
void LoadWallpaper (LPSTR imagePath)
 
void DrawWallpaper (HDC hdc)
 
void CheckWidgetPlacement (Placement *widget)
 
LRESULT MouseAndDropHandler (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
bool GetClockText (bool forceUpdate)
 
bool GetGreetingText (bool forceUpdate)
 
void ShadeWindow ()
 
void WinShade (HWND hwnd, int listIndex, bool maximized)
 
void WinUnshade (HWND hwnd, int listIndex, bool maximized)
 
void GrowWindowHeight ()
 
void GrowWindowWidth ()
 
void LowerWindow ()
 
void RaiseWindow ()
 

Public Attributes

HINSTANCE hDesktopInstance
 
HWND hBlackboxWnd
 
HWND hDesktopWnd
 
HDC cachedBackground
 
int DesktopX
 
int DesktopY
 
int DesktopWidth
 
int DesktopHeight
 
int DesktopCenterX
 
int DesktopCenterY
 
wchar_t CurrentTime [32]
 
wchar_t CurrentWeekday [32]
 
wchar_t CurrentDate [MAX_LINE_LENGTH]
 
wchar_t CurrentGreeting [32]
 
int displayedMinute
 
time_t systemTime
 
struct tm localTime
 
int currentHour
 
int currentMinute
 
RECT clockRect
 
RECT weekdayRect
 
RECT dateRect
 
RECT greetingRect
 
int numberOfDisplayMonitors
 
WallpaperStruct wallpaper
 

Friends

LRESULT CALLBACK DesktopWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 

Member Typedef Documentation

◆ WallpaperStruct

typedef struct Desktop::WallpaperStruct Desktop::WallpaperStruct

Constructor & Destructor Documentation

◆ Desktop()

Desktop::Desktop ( HINSTANCE hInstance)
50{
51 hDesktopWnd = NULL;
53 hDesktopInstance = hInstance;
54 cachedBackground = CreateCompatibleDC(NULL);
55 wallpaper.bitmap = NULL;
56
58
59 numberOfDisplayMonitors = GetSystemMetrics(SM_CMONITORS);
60
61 //====================
62
63 // Get size and position for the desktop window...
65 // ...and get the current time for the desktop clock...
66 GetClockText(true);
67 GetGreetingText(true);
68
69 if (!pSettings->underExplorer && pSettings->debugLogging) LoadWallpaper("c:\\Blackbox\\wallpapers\\reddit\\21x0pf6kq5ta1.png"); // EXPERIMENTAL & TEMPORARY :)
70
71 //====================
72
73 // Register window class...
74 WNDCLASS wc;
75 ZeroMemory(&wc, sizeof(wc));
76 wc.hInstance = hDesktopInstance; // hInstance
77 wc.lpfnWndProc = DesktopWndProc; // window procedure
78 wc.lpszClassName = szDesktopName; // window class name
79 wc.hbrBackground = NULL; // no class background brush
80 wc.style = CS_DBLCLKS; // class styles (e.g. accept doubleclicks)
81 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // always display the regular arrow cursor
82
83 if (!RegisterClass(&wc))
84 {
85 MessageBox(0, "Error registering desktop window class!", szDesktopName, MB_OK | MB_ICONERROR | MB_TOPMOST);
86 Log("Desktop: Error registering window class", NULL);
87 return;
88 }
89
90 // Create desktop window...
91 hDesktopWnd = CreateWindowEx(
92 WS_EX_TOOLWINDOW | WS_EX_ACCEPTFILES | WS_EX_NOACTIVATE | WS_EX_LAYERED, // window style
93 szDesktopName, // window class
94 NULL, // window name
95 WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // window parameters
96 DesktopX, // x position
97 DesktopY, // y position
98 DesktopWidth, // window width
99 DesktopHeight, // window height
100 NULL, // owner window
101 NULL, // no menu
102 hDesktopInstance, // hInstance
103 NULL // no window creation data
104 );
105
106 if (!hDesktopWnd)
107 {
108 UnregisterClass(szDesktopName, hDesktopInstance); // unregister window class
109 MessageBox(0, "Error creating desktop window!", szDesktopName, MB_OK | MB_ICONERROR | MB_TOPMOST);
110 Log("Desktop: Error creating window!", NULL);
111 return;
112 }
113
114 //====================
115
116 // Subscribe to Blackbox messages applicable to the desktop...
118
119 // Make the desktop window sticky...
121 // Move the desktop window to the bottom of the application z-order... (i.e. just above the Windows desktop in our case)
122// SetWindowPos(hDesktopWnd, GetDesktopWindow(), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOOWNERZORDER);
123 SetWindowPos(hDesktopWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOOWNERZORDER);
124
125 // Show+update the desktop window...
126 ShowWindow(hDesktopWnd, SW_SHOWNOACTIVATE);
128
129 // Set timer for the desktop clock update checks... (every 10 seconds, but only updating the desktop/clock if needed)
130 if (!SetTimer(hDesktopWnd, DESKTOP_UPDATE_TIMER, 10000, (TIMERPROC)NULL)) CurrentTime[0] = '\0';
131}
void MakeSticky(HWND window)
Definition BBApi.cpp:2965
#define WS_EX_LAYERED
Definition BBApi.cpp:61
void Log(LPCSTR des, LPCSTR line)
Definition BBApi.cpp:638
Settings * pSettings
Definition Blackbox.cpp:46
HWND GetBBWnd()
Definition BBApi.cpp:128
#define BB_REGISTERMESSAGE
Definition BBApi.h:142
int desktopMessageSubscription[]
Definition Desktop.cpp:45
const char szDesktopName[]
Definition Desktop.cpp:36
#define DESKTOP_UPDATE_TIMER
Definition Desktop.h:42
friend LRESULT CALLBACK DesktopWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition Desktop.cpp:151
HINSTANCE hDesktopInstance
Definition Desktop.h:80
void LoadWallpaper(LPSTR imagePath)
Definition Desktop.cpp:939
bool GetClockText(bool forceUpdate)
Definition Desktop.cpp:1263
int DesktopX
Definition Desktop.h:84
int numberOfDisplayMonitors
Definition Desktop.h:95
wchar_t CurrentWeekday[32]
Definition Desktop.h:87
bool GetGreetingText(bool forceUpdate)
Definition Desktop.cpp:1300
void GetDimensions()
Definition Desktop.cpp:909
void UpdateDesktopWindow()
Definition Desktop.cpp:315
HWND hDesktopWnd
Definition Desktop.h:81
HDC cachedBackground
Definition Desktop.h:82
wchar_t CurrentTime[32]
Definition Desktop.h:87
int DesktopWidth
Definition Desktop.h:84
WallpaperStruct wallpaper
Definition Desktop.h:111
wchar_t CurrentGreeting[32]
Definition Desktop.h:87
int DesktopHeight
Definition Desktop.h:84
int DesktopY
Definition Desktop.h:84
wchar_t CurrentDate[MAX_LINE_LENGTH]
Definition Desktop.h:87
HWND hBlackboxWnd
Definition Desktop.h:81
bool underExplorer
Definition Settings.h:368
bool debugLogging
Definition Settings.h:361

◆ ~Desktop()

Desktop::~Desktop ( )
136{
138
139 // Unsubscribe to previously subscribed Blackbox messages...
141
142 if (hDesktopWnd) DestroyWindow(hDesktopWnd); // Destroy window...
143 UnregisterClass(szDesktopName, hDesktopInstance); // Unregister window class...
144
145 if (wallpaper.bitmap != NULL) DeleteObject(wallpaper.bitmap); // Delete any cached bitmap...
146 if (cachedBackground != NULL) DeleteDC(cachedBackground); // Delete the cached gradient...
147}
#define BB_UNREGISTERMESSAGE
Definition BBApi.h:143

Member Function Documentation

◆ UpdateDesktopWindow()

void Desktop::UpdateDesktopWindow ( )
316{
317 // Fetch the new size and position parameters for the desktop window...
319
320 RECT r;
321 SetRect(&r, 0, 0, DesktopWidth, DesktopHeight);
322
323 HDC hdc = GetWindowDC(hDesktopWnd);
324 HBITMAP bufbmp = CreateCompatibleBitmap(hdc, r.right - r.left, r.bottom - r.top);
325 DeleteObject(SelectObject(cachedBackground, bufbmp));
326 ReleaseDC(hDesktopWnd, hdc);
327
328 //====================
329
330 HBRUSH brush = NULL;
331
332 if (!pSettings->underExplorer && (wallpaper.bitmap != NULL))
333 {
334 SetRect(&r, 0, 0, DesktopWidth, DesktopHeight);
337 }
338 else
339 {
340 // Draw desktop background...
341 HBRUSH brush = CreateSolidBrush(0x000000);
342 FillRect(cachedBackground, &r, brush);
343 DeleteObject(brush);
344
345 // Apply almost full transparency -> The desktop is still there and we can click it etc, but the regular Windows wallpaper can be seen!
346 SetRect(&r, 0, 0, DesktopWidth, DesktopHeight);
348 {
350 InflateRect(&r, (-4 * pSettings->scalingFactorHiDPI), (-4 * pSettings->scalingFactorHiDPI));
351 }
353 // if (!pSettings->desktopBorderHidden) AlphaCorner(cachedBackground, r, CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT, 0, 0, 0, 0, 64, 1);
354 // AlphaApply(cachedBackground, r);
355 }
356
357 //====================
358
360 {
361 // Draw workspace indicators... (nb. their default position is near top center, but if the toolbar placement is top something we put them near bottom center instead)
362 char workspacePlacement[20] = "\0";
363 Placement workspaceIndicators;
365 workspaceIndicators.height = (9 * pSettings->scalingFactorHiDPI);
368 {
369 sprintf(workspacePlacement, "Manual xC y-%d", r.top + (9*pSettings->scalingFactorHiDPI));
370 }
371 else
372 {
373 sprintf(workspacePlacement, "Manual xC y%d", r.top + (9*pSettings->scalingFactorHiDPI));
374 }
375 pSettings->ParsePlacement(workspacePlacement, &workspaceIndicators);
376 pSettings->PositionFromPlacement(&workspaceIndicators);
377// CheckWidgetPlacement(&workspaceIndicators);
378
379 SetRect(&r, workspaceIndicators.x, workspaceIndicators.y, workspaceIndicators.x+(16*pSettings->scalingFactorHiDPI), workspaceIndicators.y+(9*pSettings->scalingFactorHiDPI));
380
381// brush = CreateSolidBrush(0xffffff);
382 brush = CreateSolidBrush(pSettings->desktopWidgetColor);
383 for (int i=0; i<pSettings->numberOfWorkspaces; i++)
384 {
385 FillRect(cachedBackground, &r, brush);
387 else AlphaRect(cachedBackground, r, 64);
388 OffsetRect(&r, (20*pSettings->scalingFactorHiDPI), 0);
389 }
390 DeleteObject(brush);
391 }
392
393 //====================
394
395 // Draw greeting...?
397 {
398 HFONT font;
400 {
401 font = CreateFont((pSettings->desktopGreetingFontHeight * pSettings->scalingFactorHiDPI), 0, 0, 0, pSettings->desktopGreetingFontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pSettings->desktopGreetingFont);
402 }
403 else
404 {
405 int fontHeight = 30 * pSettings->scalingFactorHiDPI;
406 font = CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
407 }
408 HGDIOBJ oldfont = SelectObject(cachedBackground, font);
409 SetBkMode(cachedBackground, TRANSPARENT);
410
411 SIZE size;
412 GetTextExtentPoint32W(cachedBackground, CurrentGreeting, wcslen(CurrentGreeting), &size);
415
417 {
421 }
422 else // PLACEMENT_DEFAULT
423 {
427 else greetingRect.top = 320;
429 }
430
432 DrawTextWithEffectsUnicode(cachedBackground, greetingRect, CurrentGreeting, DT_CENTER | DT_TOP | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
433// DrawTextWithEffectsUnicode(cachedBackground, greetingRect, CurrentGreeting, DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
434
435 DeleteObject(SelectObject(cachedBackground, oldfont));
436 }
437
438 //====================
439
440 // Draw weekday...?
442 {
443 HFONT font;
445 {
446 font = CreateFont((pSettings->desktopWeekdayFontHeight * pSettings->scalingFactorHiDPI), 0, 0, 0, pSettings->desktopWeekdayFontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pSettings->desktopWeekdayFont);
447 }
448 else
449 {
450 int fontHeight = 30 * pSettings->scalingFactorHiDPI;
451 font = CreateFont(fontHeight, 0, 0, 0, FW_BOLD, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
452 }
453 HGDIOBJ oldfont = SelectObject(cachedBackground, font);
454 SetBkMode(cachedBackground, TRANSPARENT);
455
456 SIZE size;
457 GetTextExtentPoint32W(cachedBackground, CurrentWeekday, wcslen(CurrentWeekday), &size);
460
462 {
466 }
467 else // PLACEMENT_DEFAULT
468 {
472 else weekdayRect.top = 120;
474 }
475
477 DrawTextWithEffectsUnicode(cachedBackground, weekdayRect, CurrentWeekday, DT_CENTER | DT_TOP | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
478// DrawTextWithEffectsUnicode(cachedBackground, weekdayRect, CurrentWeekday, DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
479
480 DeleteObject(SelectObject(cachedBackground, oldfont));
481 }
482
483 //====================
484
485 // Draw date...?
487 {
488 HFONT font;
490 {
491 font = CreateFont((pSettings->desktopDateFontHeight * pSettings->scalingFactorHiDPI), 0, 0, 0, pSettings->desktopDateFontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pSettings->desktopDateFont);
492 }
493 else
494 {
495 int fontHeight = 30 * pSettings->scalingFactorHiDPI;
496 font = CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
497 }
498 HGDIOBJ oldfont = SelectObject(cachedBackground, font);
499 SetBkMode(cachedBackground, TRANSPARENT);
500
501 SIZE size;
502 GetTextExtentPoint32W(cachedBackground, CurrentDate, wcslen(CurrentDate), &size);
505
507 {
511 }
512 else // PLACEMENT_DEFAULT
513 {
517 else dateRect.top = 220;
519 }
520
522// COLORREF colorMediumAlpha = RGB(pSettings->desktopDateTransparencyAlpha / 2, pSettings->desktopDateTransparencyAlpha / 2, pSettings->desktopDateTransparencyAlpha / 2);
523 DrawTextWithEffectsUnicode(cachedBackground, dateRect, CurrentDate, DT_CENTER | DT_TOP | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
524// DrawTextWithEffectsUnicode(cachedBackground, dateRect, CurrentDate, DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
525
526 DeleteObject(SelectObject(cachedBackground, oldfont));
527 }
528
529 //====================
530
531 bool clockAlphaApplied = false;
532
533 // Draw clock...?
535 {
536 if (!_stricmp(pSettings->desktopClockType, "Regular")) // -> Regular 24-hour clock (HH:MM)
537 {
538 HFONT font;
540 {
541 font = CreateFont((pSettings->desktopClockFontHeight * pSettings->scalingFactorHiDPI), 0, 0, 0, pSettings->desktopClockFontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pSettings->desktopClockFont);
542 }
543 else
544 {
545 int fontHeight = 180 * pSettings->scalingFactorHiDPI;
546 font = CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
547 }
548 HGDIOBJ oldfont = SelectObject(cachedBackground, font);
549 SetBkMode(cachedBackground, TRANSPARENT);
550
551 SIZE size;
552 GetTextExtentPoint32W(cachedBackground, CurrentTime, wcslen(CurrentTime), &size);
555
557 {
561 }
562 else // PLACEMENT_DEFAULT
563 {
567 else clockRect.top = 20;
569 }
570
572 DrawTextWithEffectsUnicode(cachedBackground, clockRect, CurrentTime, DT_CENTER | DT_TOP | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
573// DrawTextWithEffectsUnicode(cachedBackground, clockRect, CurrentTime, DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
574
575 DeleteObject(SelectObject(cachedBackground, oldfont));
576 }
577
578 //====================
579
580 else if (!_stricmp(pSettings->desktopClockType, "Text")) // -> "Text clock" using simple 12 hour format, e.g. "TWENTY past EIGHT" (regardless of AM/PM)
581 {
582 HFONT font;
584 {
585 font = CreateFont((pSettings->desktopClockFontHeight * pSettings->scalingFactorHiDPI), 0, 0, 0, pSettings->desktopClockFontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pSettings->desktopClockFont);
586 }
587 else
588 {
589 int fontHeight = 30 * pSettings->scalingFactorHiDPI;
590 font = CreateFont(fontHeight, 0, 0, 0, FW_BOLD, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
591 }
592 HGDIOBJ oldfont = SelectObject(cachedBackground, font);
593 SetBkMode(cachedBackground, TRANSPARENT);
594
595 char textMinutes[32] = "", textInBetween[32] = "", textHours[32] = "", textAfter[32] = "", textClock[128] = "";
596
597 int relativeMinute = currentMinute;
598 if (currentMinute > 30) relativeMinute = 60 - currentMinute;
599
600 if (relativeMinute < 30)
601 {
602 if (relativeMinute >= 20)
603 {
604 strcat(textMinutes, "TWENTY");
605 switch (relativeMinute - 20)
606 {
607 case 9: { strcat(textMinutes, " NINE"); break; }
608 case 8: { strcat(textMinutes, " EIGHT"); break; }
609 case 7: { strcat(textMinutes, " SEVEN"); break; }
610 case 6: { strcat(textMinutes, " SIX"); break; }
611 case 5: { strcat(textMinutes, " FIVE"); break; }
612 case 4: { strcat(textMinutes, " FOUR"); break; }
613 case 3: { strcat(textMinutes, " THREE"); break; }
614 case 2: { strcat(textMinutes, " TWO"); break; }
615 case 1: { strcat(textMinutes, " ONE"); break; }
616 case 0: { break; }
617 }
618 }
619 else if (relativeMinute >= 10)
620 {
621 switch (relativeMinute - 10)
622 {
623 case 9: { strcat(textMinutes, "NINETEEN"); break; }
624 case 8: { strcat(textMinutes, "EIGHTEEN"); break; }
625 case 7: { strcat(textMinutes, "SEVENTEEN"); break; }
626 case 6: { strcat(textMinutes, "SIXTEEN"); break; }
627 case 5: { strcat(textMinutes, "QUARTER "); break; }
628 case 4: { strcat(textMinutes, "FOURTEEN"); break; }
629 case 3: { strcat(textMinutes, "THIRTEEN"); break; }
630 case 2: { strcat(textMinutes, "TWELVE"); break; }
631 case 1: { strcat(textMinutes, "ELEVEN"); break; }
632 case 0: { strcat(textMinutes, "TEN"); break; }
633 }
634 }
635 else if (relativeMinute >= 0)
636 {
637 switch (relativeMinute)
638 {
639 case 9: { strcat(textMinutes, "NINE"); break; }
640 case 8: { strcat(textMinutes, "EIGHT"); break; }
641 case 7: { strcat(textMinutes, "SEVEN"); break; }
642 case 6: { strcat(textMinutes, "SIX"); break; }
643 case 5: { strcat(textMinutes, "FIVE"); break; }
644 case 4: { strcat(textMinutes, "FOUR"); break; }
645 case 3: { strcat(textMinutes, "THREE"); break; }
646 case 2: { strcat(textMinutes, "TWO"); break; }
647 case 1: { strcat(textMinutes, "ONE"); break; }
648 }
649 }
650
651 if (relativeMinute == 1) strcat(textInBetween, " minute ");
652 else if ((relativeMinute > 1) && (relativeMinute != 15)) strcat(textInBetween, " minutes ");
653
654 if ((currentMinute > 0) && (currentMinute <= 30)) strcat(textInBetween, "past ");
655 else if (relativeMinute > 0) strcat(textInBetween, "to ");
656 }
657 else if (currentMinute == 30)
658 {
659 strcat(textMinutes, "HALF");
660 strcat(textInBetween, " past ");
661 }
662
663 int relativeHour = currentHour;
664 if (currentMinute > 30) relativeHour += 1;
665 if (relativeHour >= 24) relativeHour -= 24;
666 switch (relativeHour)
667 {
668 case 12: { strcat(textHours, "NOON"); break; }
669 case 11: case 23: { strcat(textHours, "ELEVEN"); break; }
670 case 10: case 22: { strcat(textHours, "TEN"); break; }
671 case 9: case 21: { strcat(textHours, "NINE"); break; }
672 case 8: case 20: { strcat(textHours, "EIGHT"); break; }
673 case 7: case 19: { strcat(textHours, "SEVEN"); break; }
674 case 6: case 18: { strcat(textHours, "SIX"); break; }
675 case 5: case 17: { strcat(textHours, "FIVE"); break; }
676 case 4: case 16: { strcat(textHours, "FOUR"); break; }
677 case 3: case 15: { strcat(textHours, "THREE"); break; }
678 case 2: case 14: { strcat(textHours, "TWO"); break; }
679 case 1: case 13: { strcat(textHours, "ONE"); break; }
680 case 0: { strcat(textHours, "MIDNIGHT"); break; }
681 }
682
683 if ((currentMinute == 0) && (currentHour != 0) && (currentHour != 12)) strcat(textAfter, " o'clock");
684
685 sprintf(textClock, "%s%s%s%s", textMinutes, textInBetween, textHours, textAfter);
686
687 SIZE size;
688 GetTextExtentPoint32(cachedBackground, textClock, strlen(textClock), &size);
691
693 {
697 }
698 else // PLACEMENT_DEFAULT
699 {
702// if (pSettings->doubleScaleHiDPI) clockRect.top = 32;
703 if (pSettings->scalingFactorHiDPI > 1) clockRect.top = 32;
704 else clockRect.top = 30;
706
707 pSettings->desktopClockPlacement.x = clockRect.left; // ...we keep a copy of clockRect.left to be able to restore it later... (see below)
708 }
709
712
713 if (strlen(textMinutes) > 0)
714 {
715 DrawTextWithEffects(cachedBackground, clockRect, textMinutes, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
716 GetTextExtentPoint32(cachedBackground, textMinutes, strlen(textMinutes), &size);
717 clockRect.left += size.cx;
718
719 DrawTextWithEffects(cachedBackground, clockRect, textInBetween, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorMediumAlpha, false, 0, false, 0, 0, 0);
720 GetTextExtentPoint32(cachedBackground, textInBetween, strlen(textInBetween), &size);
721 clockRect.left += size.cx;
722 }
723
724 DrawTextWithEffects(cachedBackground, clockRect, textHours, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorHighAlpha, false, 0, false, 0, 0, 0);
725
726 if (strlen(textAfter) > 0)
727 {
728 GetTextExtentPoint32(cachedBackground, textHours, strlen(textHours), &size);
729 clockRect.left += size.cx;
730 DrawTextWithEffects(cachedBackground, clockRect, textAfter, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, colorMediumAlpha, false, 0, false, 0, 0, 0);
731 }
732
734
735 DeleteObject(SelectObject(cachedBackground, oldfont));
736 }
737
738 //====================
739
740 else if (!_stricmp(pSettings->desktopClockType, "Binary")) // -> Bit clock
741 {
742 wchar_t temp;
743 int currentDigit;
744 int mediumTransparencyAlpha = pSettings->desktopClockTransparencyAlpha / 2;
745 int lowTransparencyAlpha = pSettings->desktopClockTransparencyAlpha / 8;
746
747// brush = CreateSolidBrush(0xffffff);
748 brush = CreateSolidBrush(pSettings->desktopWidgetColor);
749
751 {
753 {
759 }
760 else
761 {
767 }
768 }
769 else // PLACEMENT_DEFAULT
770 {
771 if (pSettings->doubleScaleHiDPI) SetRect(&r, DesktopCenterX-198, 49, DesktopCenterX-102, 103);
772 else SetRect(&r, DesktopCenterX-102, 49, DesktopCenterX-54, 76);
773 }
774
775 for (int x=1; x<=4; x++)
776 {
777 if (x == 1) temp = CurrentTime[0];
778 else if (x == 2) temp = CurrentTime[1];
779 else if (x == 3) temp = CurrentTime[3];
780 else if (x == 4) temp = CurrentTime[4];
781 currentDigit = _wtoi(&temp);
782
783 for (int y=1; y<=4; y++)
784 {
785 FillRect(cachedBackground, &r, brush);
786
787 if ((x == 1) && ((y == 1) || (y == 2))) AlphaRect(cachedBackground, r, lowTransparencyAlpha); // ...because the first digit can only be 0-2...
788 else
789 {
790 if ((y == 1) && (currentDigit & 8)) AlphaRect(cachedBackground, r, pSettings->desktopClockTransparencyAlpha);
791 else if ((y == 2) && (currentDigit & 4)) AlphaRect(cachedBackground, r, pSettings->desktopClockTransparencyAlpha);
792 else if ((y == 3) && (currentDigit & 2)) AlphaRect(cachedBackground, r, pSettings->desktopClockTransparencyAlpha);
793 else if ((y == 4) && (currentDigit & 1)) AlphaRect(cachedBackground, r, pSettings->desktopClockTransparencyAlpha);
794 else AlphaRect(cachedBackground, r, mediumTransparencyAlpha);
795 }
796// AlphaApply(cachedBackground, r);
797
798 if (pSettings->doubleScaleHiDPI) OffsetRect(&r, 0, 58);
799 else OffsetRect(&r, 0, 31);
800 }
801
802 if (pSettings->doubleScaleHiDPI) OffsetRect(&r, 100, -232);
803 else OffsetRect(&r, 52, -124);
804 }
805
806 clockAlphaApplied = true;
807
808 DeleteObject(brush);
809 }
810 }
811
812 //====================
813
814 // Apply per pixel alpha to the clock/weekday/date as applicable, including support for overlapping...
815 // (nb. currently at least with a fixed z-order i.e. weekday-date-clock from the bottom up as per the order drawn above)
816 RECT tempRect;
817 bool overlapWeekdayDate = (bool)(IntersectRect(&tempRect, &weekdayRect, &dateRect) && !pSettings->desktopWeekdayHidden && !pSettings->desktopDateHidden);
818 bool overlapWeekdayDateClock = false;
819 if (overlapWeekdayDate)
820 {
821 UnionRect(&tempRect, &weekdayRect, &dateRect);
822 overlapWeekdayDateClock = (bool)(IntersectRect(&tempRect, &tempRect, &clockRect) && !pSettings->desktopClockHidden && !clockAlphaApplied);
823 }
824 bool overlapDateClock = (bool)(IntersectRect(&tempRect, &dateRect, &clockRect) && !pSettings->desktopDateHidden && !pSettings->desktopClockHidden && !clockAlphaApplied);
825 bool overlapWeekdayClock = (bool)(IntersectRect(&tempRect, &weekdayRect, &clockRect) && !pSettings->desktopWeekdayHidden && !pSettings->desktopClockHidden && !clockAlphaApplied);
826
827 if (overlapWeekdayDateClock) // -> All three of them overlapping
828 {
829 UnionRect(&tempRect, &weekdayRect, &dateRect);
830 UnionRect(&tempRect, &tempRect, &clockRect);
832 }
833 else if (overlapWeekdayDate)
834 {
835 UnionRect(&tempRect, &weekdayRect, &dateRect);
837
839 }
840 else if (overlapDateClock)
841 {
842 UnionRect(&tempRect, &dateRect, &clockRect);
844
846 }
847 else if (overlapWeekdayClock)
848 {
849 UnionRect(&tempRect, &weekdayRect, &clockRect);
851
853 }
854 else // -> None of them overlapping
855 {
856// if (!pSettings->desktopGreetingHidden) AlphaFromRGB(cachedBackground, greetingRect, 1, 255, true, pSettings->desktopWidgetColor);
860 }
861
862 if (!pSettings->desktopGreetingHidden) AlphaFromRGB(cachedBackground, greetingRect, 1, 255, true, pSettings->desktopWidgetColor); // TEMPORARY UNTIL OVERLAPPING IS IMPLEMENTED
863
864 //====================
865
866 SetRect(&r, 0, 0, DesktopWidth, DesktopHeight);
868
869 //====================
870
871 if (bufbmp) DeleteObject(bufbmp);
872
873 POINT pt;
874 pt.x = DesktopX, pt.y = DesktopY;
875 POINT ptSrc;
876 ptSrc.x = 0, ptSrc.y = 0;
877
878 BLENDFUNCTION bf;
879 bf.BlendOp = AC_SRC_OVER;
880 bf.BlendFlags = 0;
881 bf.AlphaFormat = AC_SRC_ALPHA;
882 bf.SourceConstantAlpha = (unsigned char)255;
883
884 SIZE windowSize = { DesktopWidth, DesktopHeight };
885 BOOL result = UpdateLayeredWindow(hDesktopWnd, NULL, &pt, &windowSize, cachedBackground, &ptSrc, 0, &bf, ULW_ALPHA);
886/*
887 if (!cachedBackground) SendMessage(GetBBWnd(), BB_CONSOLEMESSAGE, (WPARAM)CONSOLE_INFORMATION_MESSAGE, (LPARAM)"xoblite -> Desktop -> Invalid cachedBackground!");
888
889 if (result == 0)
890 {
891 int error = GetLastError();
892 char msg[255];
893 sprintf(msg, "xoblite -> Desktop -> UpdateLayeredWindow failed! [error code %d]", error);
894 SendMessage(GetBBWnd(), BB_CONSOLEMESSAGE, (WPARAM)CONSOLE_ERROR_MESSAGE, (LPARAM)msg);
895 }
896 else
897*/
898 {
899 // Finally, we move the desktop window to the bottom of the regular z-order... (i.e. just above the Windows desktop in our case)
900 SetWindowPos(hDesktopWnd, GetDesktopWindow(), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOOWNERZORDER);
901 }
902}
void AlphaFromRGB(HDC hdc, RECT rect, unsigned char minAlpha, unsigned char maxAlpha, bool recolor, COLORREF color)
Definition BBApi.cpp:2439
void AlphaApply(HDC hdc, RECT rect)
Definition BBApi.cpp:2449
void DrawTextWithEffectsUnicode(HDC hdc, RECT r, LPWSTR text, unsigned int format, COLORREF textColor, bool outline, COLORREF outlineColor, bool shadow, COLORREF shadowColor, int shadowX, int shadowY)
Definition BBApi.cpp:3528
void AlphaRect(HDC hdc, RECT rect, unsigned char alpha)
Definition BBApi.cpp:2419
void DrawTextWithEffects(HDC hdc, RECT r, LPSTR text, unsigned int format, COLORREF textColor, bool outline, COLORREF outlineColor, bool shadow, COLORREF shadowColor, int shadowX, int shadowY)
Definition BBApi.cpp:3519
#define PLACEMENT_TOP_CENTER
Definition Settings.h:69
struct Placement Placement
#define PLACEMENT_DEFAULT
Definition Settings.h:77
#define PLACEMENT_TOP_LEFT
Definition Settings.h:68
#define PLACEMENT_TOP_RIGHT
Definition Settings.h:70
void CheckWidgetPlacement(Placement *widget)
Definition Desktop.cpp:986
void DrawWallpaper(HDC hdc)
Definition Desktop.cpp:969
int currentHour
Definition Desktop.h:91
RECT clockRect
Definition Desktop.h:93
RECT dateRect
Definition Desktop.h:93
int currentMinute
Definition Desktop.h:91
RECT weekdayRect
Definition Desktop.h:93
int DesktopCenterX
Definition Desktop.h:85
RECT greetingRect
Definition Desktop.h:93
char desktopDateFont[128]
Definition Settings.h:276
int scalingFactorHiDPI
Definition Settings.h:327
Placement desktopGreetingPlacement
Definition Settings.h:281
Placement desktopClockPlacement
Definition Settings.h:256
int currentWorkspace
Definition Settings.h:372
char desktopClockType[MAX_LINE_LENGTH]
Definition Settings.h:255
int desktopDateFontHeight
Definition Settings.h:277
BYTE desktopDateTransparencyAlpha
Definition Settings.h:274
bool desktopClockHidden
Definition Settings.h:254
bool doubleScaleHiDPI
Definition Settings.h:326
bool desktopWeekdayHidden
Definition Settings.h:263
Placement desktopDatePlacement
Definition Settings.h:273
void PositionFromPlacement(Placement *inputPlacement)
Definition Settings.cpp:3236
int desktopClockFontHeight
Definition Settings.h:260
char desktopGreetingFont[128]
Definition Settings.h:284
bool toolbarHidden
Definition Settings.h:188
int desktopGreetingFontWeight
Definition Settings.h:286
BYTE desktopClockTransparencyAlpha
Definition Settings.h:257
int desktopClockFontWeight
Definition Settings.h:261
bool desktopWeekdayFontDefined
Definition Settings.h:266
bool desktopClockFontDefined
Definition Settings.h:258
int desktopDateFontWeight
Definition Settings.h:278
Placement ToolbarPlacement
Definition Settings.h:189
bool desktopGreetingFontDefined
Definition Settings.h:283
bool desktopBorderHidden
Definition Settings.h:293
char desktopClockFont[128]
Definition Settings.h:259
bool desktopWorkspaceIndicatorHidden
Definition Settings.h:292
COLORREF desktopWidgetColor
Definition Settings.h:295
int desktopWeekdayFontWeight
Definition Settings.h:269
void ParsePlacement(LPSTR inputString, Placement *outputPlacement)
Definition Settings.cpp:3121
bool desktopDateFontDefined
Definition Settings.h:275
bool desktopGreetingHidden
Definition Settings.h:280
bool desktopDateHidden
Definition Settings.h:271
int numberOfWorkspaces
Definition Settings.h:306
Placement desktopWeekdayPlacement
Definition Settings.h:264
int desktopGreetingFontHeight
Definition Settings.h:285
BYTE desktopWeekdayTransparencyAlpha
Definition Settings.h:265
char desktopWeekdayFont[128]
Definition Settings.h:267
int desktopWeekdayFontHeight
Definition Settings.h:268
BYTE desktopGreetingTransparencyAlpha
Definition Settings.h:282
int placement
Definition Settings.h:89
int height
Definition Settings.h:97
int width
Definition Settings.h:96
int x
Definition Settings.h:94
int y
Definition Settings.h:95

◆ GetDimensions()

void Desktop::GetDimensions ( )
910{
911/*
912 if (!pSettings->explorerHidden)
913 {
914 RECT workArea;
915 SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&workArea, SPIF_SENDCHANGE);
916 DesktopWidth = workArea.right - workArea.left;
917 DesktopHeight = workArea.bottom - workArea.top;
918 DesktopX = workArea.left;
919 DesktopY = workArea.top;
920 }
921 else
922*/
923 {
924 DesktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
925 DesktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
926 DesktopX = GetSystemMetrics(SM_XVIRTUALSCREEN);
927 DesktopY = GetSystemMetrics(SM_YVIRTUALSCREEN);
928 }
929
932}
int DesktopCenterY
Definition Desktop.h:85

◆ LoadWallpaper()

void Desktop::LoadWallpaper ( LPSTR imagePath)
940{
941 if (!FileExists(imagePath)) return;
942
943 if (wallpaper.bitmap != NULL) DeleteObject(wallpaper.bitmap);
944
945 // Load the image using GDI+ to add support for JPG, PNG etc...
946 // (nb. regular GDI LoadImage() only supports BMP images. GDI+ startup/shutdown is performed "globally" in Blackbox.cpp.)
947 wchar_t imagePathWC[MAX_PATH];
948 MultiByteToWideChar(CP_ACP, 0, imagePath, strlen(imagePath) + 1, imagePathWC, MAX_PATH);
949 Bitmap* bitmap = new Bitmap(imagePathWC, FALSE);
950
951 // ...fetch some of its properties...
952 wallpaper.width = bitmap->GetWidth();
953 wallpaper.height = bitmap->GetHeight();
954 PixelFormat pf = bitmap->GetPixelFormat();
955 if ((pf == PixelFormat32bppARGB) || (pf == PixelFormat32bppPARGB) || (pf == PixelFormat64bppARGB) || (pf == PixelFormat64bppPARGB)) wallpaper.argb = true;
956 else wallpaper.argb = false;
957
958 // ...and finally create our target GDI HBITMAP from the loaded GDI+ Bitmap...
959 bitmap->GetHBITMAP(0, &wallpaper.bitmap);
960
961 delete bitmap;
962}
bool FileExists(LPCSTR szFileName)
Definition BBApi.cpp:819

◆ DrawWallpaper()

void Desktop::DrawWallpaper ( HDC hdc)
970{
971 if (wallpaper.bitmap == NULL) return;
972
973 HDC buf = CreateCompatibleDC(hdc);
974 DeleteObject(SelectObject(buf, wallpaper.bitmap));
975 SetStretchBltMode(hdc, HALFTONE);
976 StretchBlt(hdc, 0, 0, DesktopWidth, DesktopHeight, buf, 0, 0, wallpaper.width, wallpaper.height, SRCCOPY);
977
978 DeleteDC(buf);
979}

◆ CheckWidgetPlacement()

void Desktop::CheckWidgetPlacement ( Placement * widget)
987{
988 // Adjust from screen relative to desktop relative coordinates...
989 // (cf. e.g. Explorer taskbar along left or top screen edges)
990 widget->x -= DesktopX;
991 widget->y -= DesktopY;
992
993 // Adjust for the semi-transparent desktop border... (if visible)
994 if (pSettings->desktopBorderHidden) return;
995
996 if ((widget->placement == PLACEMENT_TOP_LEFT)
997 || (widget->placement == PLACEMENT_CENTER_LEFT)
998 || (widget->placement == PLACEMENT_BOTTOM_LEFT))
999 {
1000 widget->x += 20;
1001 }
1002
1003 if ((widget->placement == PLACEMENT_TOP_RIGHT)
1004 || (widget->placement == PLACEMENT_CENTER_RIGHT)
1005 || (widget->placement == PLACEMENT_BOTTOM_RIGHT))
1006 {
1007 widget->x -= 20;
1008 }
1009
1010 if ((widget->placement == PLACEMENT_TOP_LEFT)
1011 || (widget->placement == PLACEMENT_TOP_RIGHT))
1012 {
1013 widget->y += 20;
1014 }
1015
1017 {
1018 // Stay clear of the workspace indicators if they're visible...
1019 widget->y += 39;
1020 }
1021
1022 if ((widget->placement == PLACEMENT_BOTTOM_LEFT)
1023 || (widget->placement == PLACEMENT_BOTTOM_CENTER)
1024 || (widget->placement == PLACEMENT_BOTTOM_RIGHT))
1025 {
1026 widget->y -= 20;
1027 }
1028}
#define PLACEMENT_CENTER_LEFT
Definition Settings.h:71
#define PLACEMENT_BOTTOM_CENTER
Definition Settings.h:75
#define PLACEMENT_BOTTOM_LEFT
Definition Settings.h:74
#define PLACEMENT_BOTTOM_RIGHT
Definition Settings.h:76
#define PLACEMENT_CENTER_RIGHT
Definition Settings.h:73

◆ MouseAndDropHandler()

LRESULT Desktop::MouseAndDropHandler ( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
1059{
1060 switch (uMsg)
1061 {
1062 //====================
1063
1064 case WM_LBUTTONUP:
1065 {
1066 if (pMenuCommon)
1067 {
1068// if (GetAsyncKeyState(VK_MENU) & 0x8000)
1069// {
1070// SendMessage(GetBBWnd(), BB_MENU, 0, 0); // Alt+LeftClick -> Main menu
1071// PlaySoundFX(SFX_MENU_SHOW);
1072// }
1073// else
1074 {
1075 // First we set focus to the toolbar to prevent the focus from going back to the previous task after the menu is closed...
1076// if (pSettings->followActive) SetForegroundWindow(pToolbar->hToolbarWnd);
1077// if (pSettings->followActive) SetForegroundWindow(hDesktopWnd);
1078 // Move the desktop window to the bottom of the application z-order... (i.e. just above the Windows desktop in our case)
1079// SetWindowPos(hDesktopWnd, GetDesktopWindow(), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOOWNERZORDER);
1080 SetWindowPos(hDesktopWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOOWNERZORDER);
1081
1083 }
1084 }
1085 }
1086 break;
1087
1088 case WM_LBUTTONDOWN: { } break;
1089
1090 //====================
1091
1092 case WM_RBUTTONUP:
1093 {
1094 // Has the user defined an Right Click command override?
1095 if (strlen(pSettings->desktopRClickOverride) > 0)
1096 {
1097 if (GetAsyncKeyState(VK_MENU) & 0x8000)
1098 {
1099 SendMessage(GetBBWnd(), BB_MENU, 0, 0); // Alt+Right Click -> Main menu
1101 }
1102 else BBSmartExecute(pSettings->desktopRClickOverride); // Right Click without modifiers -> User defined command override
1103 }
1104
1105 // We otherwise provide a couple of Right Click + key modifier actions for people with only a *2* button mouse...
1106 else if (GetAsyncKeyState(VK_MENU) & 0x8000)
1107 {
1108 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && (GetAsyncKeyState(VK_SHIFT) & 0x8000))
1109 {
1110 SendMessage(GetBBWnd(), BB_MENU, 2, 0); // Ctrl+Alt+Shift+RightClick -> Configuration menu
1112 }
1113 else if (GetAsyncKeyState(VK_CONTROL) & 0x8000) BBSmartExecute("@xoblite Random Wallpaper"); // Ctrl+Alt+RightClick -> Apply random wallpaper (note: matching Modifier+MidClick)
1114 else if (GetAsyncKeyState(VK_SHIFT) & 0x8000) BBSmartExecute("@xoblite Random Style"); // Shift+Alt+RightClick -> Apply random style (note: matching Modifier+MidClick)
1115 else
1116 {
1117 SendMessage(GetBBWnd(), BB_MENU, 5, 0); // Alt+RightClick -> Styles menu
1119 }
1120 }
1121 else if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1122 {
1123 SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Ctrl+RightClick -> Themes menu
1125 }
1126 else if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
1127 {
1128 SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Shift+RightClick -> Workspaces menu
1130// BBSmartExecute("@xoblite Random Wallpaper"); // Shift+RightClick -> Apply random wallpaper
1131 }
1132 else
1133 {
1134 SendMessage(GetBBWnd(), BB_MENU, 0, 0); // RightClick without modifiers -> Main menu
1136 }
1137 }
1138 break;
1139
1140 case WM_RBUTTONDOWN: { } break;
1141
1142 //====================
1143
1144 case WM_MBUTTONUP:
1145 {
1146 // Has the user defined an Mid Click command override?
1147 if (strlen(pSettings->desktopMClickOverride) > 0)
1148 {
1149 if (GetAsyncKeyState(VK_MENU) & 0x8000)
1150 {
1151 SendMessage(GetBBWnd(), BB_MENU, 5, 0); // Alt+Mid Click -> Styles menu
1153 }
1154 else BBSmartExecute(pSettings->desktopMClickOverride); // Mid Click without modifiers -> User defined command override
1155 }
1156
1157 // We otherwise provide a couple of Mid Click + key modifier actions for people with only a *3* button mouse...
1158 else if (GetAsyncKeyState(VK_MENU) & 0x8000)
1159 {
1160 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) BBSmartExecute("@xoblite Random Wallpaper"); // Ctrl+Alt+MidClick -> Apply random wallpaper (note: matching Modifier+RightClick)
1161 else if (GetAsyncKeyState(VK_SHIFT) & 0x8000) BBSmartExecute("@xoblite Random Style"); // Shift+Alt+MidClick -> Apply random style (note: matching Modifier+RightClick)
1162 else
1163 {
1164 SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Alt+MidClick -> Themes menu
1166 }
1167 }
1168 else
1169 {
1170 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Ctrl+MidClick -> Workspaces menu
1171 else if (GetAsyncKeyState(VK_SHIFT) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 2, 0); // Shift+MidClick -> Configuration menu
1172 else SendMessage(GetBBWnd(), BB_MENU, 5, 0); // MidClick without modifiers -> Styles menu
1174 }
1175 }
1176 break;
1177
1178 case WM_MBUTTONDOWN: { } break;
1179
1180 //====================
1181
1182 case WM_XBUTTONDOWN:
1183 {
1184 if (HIWORD(wParam) == XBUTTON1)
1185 {
1186 if (strlen(pSettings->desktopX1ClickOverride) > 0) // Has the user defined an X1 click command override?
1187 {
1188 if (GetAsyncKeyState(VK_MENU) & 0x8000)
1189 {
1190 SendMessage(GetBBWnd(), BB_MENU, 6, 0); // Alt+X1 Click -> Themes menu
1192 }
1193 else BBSmartExecute(pSettings->desktopX1ClickOverride); // X1 Click without modifiers -> User defined command override
1194 }
1195 else if (GetAsyncKeyState(VK_MENU) & 0x8000) BBSmartExecute("@xoblite Random Wallpaper"); // Alt+X1 Click -> Apply random wallpaper
1196 else
1197 {
1198 // if (GetAsyncKeyState(VK_CONTROL) & 0x8000) BBSmartExecute("@xoblite About"); // Placeholder, possibly for use defined command?
1199 if (GetAsyncKeyState(VK_SHIFT) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 2, 0); // Shift+X1 Click -> Configuration menu
1200 else SendMessage(GetBBWnd(), BB_MENU, 6, 0); // X1 Click without modifiers -> Themes menu
1202 }
1203 }
1204 else if (HIWORD(wParam) == XBUTTON2)
1205 {
1206 if (strlen(pSettings->desktopX2ClickOverride) > 0) // Has the user defined an X2 click command override?
1207 {
1208 if (GetAsyncKeyState(VK_MENU) & 0x8000)
1209 {
1210 SendMessage(GetBBWnd(), BB_MENU, 1, 0); // Alt+X2 Click -> Workspaces menu
1212 }
1213 else BBSmartExecute(pSettings->desktopX2ClickOverride); // X2 Click without modifiers -> User defined command override
1214 }
1215 else if (GetAsyncKeyState(VK_MENU) & 0x8000) BBSmartExecute("@xoblite Random Style"); // Alt+X2 Click -> Apply random style
1216 else
1217 {
1218 // if (GetAsyncKeyState(VK_CONTROL) & 0x8000) BBSmartExecute("@xoblite About"); // Placeholder, possibly for use defined command?
1219 if (GetAsyncKeyState(VK_SHIFT) & 0x8000) SendMessage(GetBBWnd(), BB_MENU, 2, 0); // Shift+X2 Click -> Configuration menu
1220 else SendMessage(GetBBWnd(), BB_MENU, 1, 0); // X2 Click without modifiers -> Workspaces menu
1222 }
1223 }
1224 }
1225 break;
1226
1227 case WM_XBUTTONUP: { } break;
1228
1229 //====================
1230
1231 case WM_MOUSEWHEEL:
1232 {
1234 {
1235 if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) pWorkspaces->NextWorkspace(); // Mousewheel down -> Move to the next workspace...
1236 else pWorkspaces->PreviousWorkspace(); // Mousewheel up -> Move to the previous workspace...
1237 }
1238 }
1239 break;
1240
1241 // case WM_MOUSEHWHEEL: { } break;
1242
1243 //====================
1244
1245 case WM_DROPFILES:
1246 {
1247 return ParseDropFiles(hWnd, wParam);
1248 }
1249 break;
1250
1251 //====================
1252
1253 default:
1254 return DefWindowProc(hWnd, uMsg, wParam, lParam);
1255
1256 //====================
1257 }
1258 return 0;
1259}
int ParseDropFiles(HWND hwnd, WPARAM wParam)
Definition BBApi.cpp:3381
Workspaces * pWorkspaces
Definition Blackbox.cpp:51
void BBSmartExecute(LPSTR inputString)
Definition BBApi.cpp:1767
MenuCommon * pMenuCommon
Definition Blackbox.cpp:41
#define BB_MENU
Definition BBApi.h:160
void PlaySoundFX(int sound)
Definition Sounds.cpp:40
@ SFX_MENU_SHOW
Definition Sounds.h:42
bool Hide(int index=0)
Definition MenuCommon.cpp:1028
char desktopX1ClickOverride[MAX_LINE_LENGTH]
Definition Settings.h:299
char desktopRClickOverride[MAX_LINE_LENGTH]
Definition Settings.h:297
char desktopMClickOverride[MAX_LINE_LENGTH]
Definition Settings.h:298
char desktopX2ClickOverride[MAX_LINE_LENGTH]
Definition Settings.h:300
bool mousewheelChanging
Definition Settings.h:308
void NextWorkspace()
Definition Workspaces.cpp:369
void PreviousWorkspace()
Definition Workspaces.cpp:359

◆ GetClockText()

bool Desktop::GetClockText ( bool forceUpdate)
1264{
1265 time(&systemTime);
1266 localtime_s(&localTime, &systemTime);
1267 currentHour = localTime.tm_hour;
1268 currentMinute = localTime.tm_min;
1269
1270 // Only update the desktop clock if the current minute has changed...
1271 if ((currentMinute != displayedMinute) || forceUpdate)
1272 {
1273 // Get the time string for the regular clock...
1274 if (IsInString(pSettings->toolbarClockFormat, "%I")) wcsftime(CurrentTime, sizeof(CurrentTime), L"%I:%M %p", &localTime); // 12-hour format including AM/PM indicator
1275 else wcsftime(CurrentTime, sizeof(CurrentTime), L"%H:%M", &localTime); // 24-hour format
1276 // Remember minute shown in display, now wait until minute changes before updating again...
1278
1279 // Get the weekday string...
1280 wcsftime(CurrentWeekday, sizeof(CurrentWeekday), L"%A", &localTime); // Day of the week as per the current locale (e.g. "Saturday")
1281
1282 // Get the configurable date string... (nb. we need to convert the format string from ANSI to Unicode first)
1283 wchar_t desktopDateFormatInUnicode[MAX_LINE_LENGTH];
1284 MultiByteToWideChar(CP_UTF8, 0, pSettings->desktopDateFormat, strlen(pSettings->desktopDateFormat)+1, desktopDateFormatInUnicode, MAX_LINE_LENGTH);
1285 wcsftime(CurrentDate, sizeof(CurrentDate), desktopDateFormatInUnicode, &localTime); // Configurable date string (cf. the toolbar clock's format string and related options)
1286
1287 if (!forceUpdate)
1288 {
1291 }
1292
1293 return true;
1294 }
1295 else return false;
1296}
bool IsInString(LPCSTR inputString, LPCSTR searchString)
Definition BBApi.cpp:2519
#define MAX_LINE_LENGTH
Definition BBApi.h:64
@ SFX_CLOCK_HOUR
Definition Sounds.h:58
@ SFX_CLOCK_HALFHOUR
Definition Sounds.h:59
int displayedMinute
Definition Desktop.h:88
time_t systemTime
Definition Desktop.h:89
struct tm localTime
Definition Desktop.h:90
char desktopDateFormat[MAX_LINE_LENGTH]
Definition Settings.h:272
char toolbarClockFormat[MAX_LINE_LENGTH]
Definition Settings.h:202

◆ GetGreetingText()

bool Desktop::GetGreetingText ( bool forceUpdate)
1301{
1302 time(&systemTime);
1303 localtime_s(&localTime, &systemTime);
1304
1305 if (localTime.tm_hour < 6) wcscpy_s(CurrentGreeting, 32, L"Good night"); // 00-06 -> "Good night"
1306 else if (localTime.tm_hour < 12) wcscpy_s(CurrentGreeting, 32, L"Good morning"); // 06-12 -> "Good morning"
1307 else if (localTime.tm_hour < 18) wcscpy_s(CurrentGreeting, 32, L"Good afternoon"); // 12-18 -> "Good afternoon"
1308 else wcscpy_s(CurrentGreeting, 32, L"Good evening"); // 18-24 -> "Good evening"
1309
1310 return true;
1311}

◆ ShadeWindow()

void Desktop::ShadeWindow ( )
1320{
1321 HWND currentWnd = pTaskbar->GetActiveWindow();
1322 BOOL isMaximized = IsZoomed(currentWnd);
1323
1324 RECT r;
1325 GetWindowRect(currentWnd, &r);
1326 int titleBarHeight = GetSystemMetrics(SM_CYMIN);
1327 bool isUnshaded = (r.bottom-r.top > titleBarHeight);
1328
1329// i = IsFlaggedShaded(currentWnd);
1330 int i = (int)(GetProp(currentWnd, "BBNormalHeight") != NULL);
1331
1332 if (isMaximized)
1333 {
1334 if (isUnshaded) WinShade(currentWnd, -1, isMaximized);
1335 else WinUnshade(currentWnd, -1, isMaximized);
1336 }
1337 else
1338 {
1339 if (i != -1) // Was the window found in our list?
1340 {
1341 if (isUnshaded) // Shade the window...
1342 {
1343 RemoveProp(currentWnd, "BBNormalHeight");
1344 WinShade(currentWnd, -1, isMaximized);
1345 }
1346 else // Unshade the window...
1347 {
1348 WinUnshade(currentWnd, i, isMaximized);
1349 }
1350 }
1351 else WinShade(currentWnd, i, isMaximized);
1352 }
1353}
Taskbar * pTaskbar
Definition Blackbox.cpp:47
void WinUnshade(HWND hwnd, int listIndex, bool maximized)
Definition Desktop.cpp:1380
void WinShade(HWND hwnd, int listIndex, bool maximized)
Definition Desktop.cpp:1361
HWND GetActiveWindow()
Definition Taskbar.cpp:413

◆ WinShade()

void Desktop::WinShade ( HWND hwnd,
int listIndex,
bool maximized )
1362{
1363 if (listIndex != -1) return;
1364
1365 RECT r;
1366 SetForegroundWindow(hwnd);
1367 GetWindowRect(hwnd, &r);
1368
1369 // Remember the window's original height...
1370 if (!maximized) SetProp(hwnd, "BBNormalHeight", (HANDLE)(r.bottom - r.top));
1371 // ...and then shrink it vertically to only show its titlebar...
1372 SetWindowPos(hwnd, HWND_TOP, r.left, r.top, r.right-r.left, GetSystemMetrics(SM_CYMIN), SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
1373}

◆ WinUnshade()

void Desktop::WinUnshade ( HWND hwnd,
int listIndex,
bool maximized )
1381{
1382 if (listIndex == -1 && !maximized) return;
1383
1384 RECT r;
1385 int height;
1386 SetForegroundWindow(hwnd);
1387
1388 if (maximized)
1389 {
1390 // This is a maximized window, so its restored height should be the height of the screen's work area...
1391 RECT workArea;
1392 SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&workArea, SPIF_SENDCHANGE);
1393 height = workArea.bottom - workArea.top;
1394 }
1395 else
1396 {
1397 // This is a non-maximized window, so we restore it to the original height previously saved...
1398 height = (long)GetProp(hwnd, "BBNormalHeight");
1399 RemoveProp(hwnd, "BBNormalHeight");
1400 }
1401
1402 if (height == 0) return;
1403
1404 GetWindowRect(hwnd, &r);
1405 MoveWindow(hwnd, r.left, r.top, r.right-r.left, height, true);
1406 InvalidateRect(hwnd, NULL, false);
1407}

◆ GrowWindowHeight()

void Desktop::GrowWindowHeight ( )
1415{
1416 HWND currentWnd = pTaskbar->GetActiveWindow();
1417 RECT r, workArea;
1418 GetWindowRect(currentWnd, &r);
1419 SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&workArea, SPIF_SENDCHANGE);
1420 MoveWindow(currentWnd, r.left, 0, r.right-r.left, workArea.bottom-workArea.top, true);
1421 InvalidateRect(currentWnd, NULL, false);
1422 SetForegroundWindow(currentWnd);
1423}

◆ GrowWindowWidth()

void Desktop::GrowWindowWidth ( )
1428{
1429 HWND currentWnd = pTaskbar->GetActiveWindow();
1430 RECT r, workArea;
1431 GetWindowRect(currentWnd, &r);
1432 SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&workArea, SPIF_SENDCHANGE);
1433 MoveWindow(currentWnd, 0, r.top, workArea.right-workArea.left, r.bottom-r.top, true);
1434 GetWindowRect(currentWnd, &r);
1435 SetForegroundWindow(currentWnd);
1436}

◆ LowerWindow()

void Desktop::LowerWindow ( )
1444{
1445 HWND currentWnd = pTaskbar->GetActiveWindow();
1446
1447 // First we fetch the bottom window...
1448 HWND bottomWnd = GetWindow(hBlackboxWnd, GW_HWNDLAST);
1449 HWND hProgManWnd = FindWindow("Progman", "Program Manager");
1450 if (bottomWnd == hProgManWnd) bottomWnd = GetWindow(bottomWnd, GW_HWNDPREV);
1451
1452 while (!IsWindowVisible(bottomWnd) || IsIconic(bottomWnd) || (GetWindowTextLength(bottomWnd) == 0))
1453 {
1454 bottomWnd = GetWindow(bottomWnd, GW_HWNDPREV);
1455 if (bottomWnd == hProgManWnd) bottomWnd = GetWindow(bottomWnd, GW_HWNDPREV);
1456 }
1457
1458 // ...and then we put the current window behind that...
1459 if (IsWindow(currentWnd) && IsWindow(bottomWnd))
1460 {
1461 SetWindowPos(currentWnd, bottomWnd, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
1462 }
1463}

◆ RaiseWindow()

void Desktop::RaiseWindow ( )
1468{
1469 HWND currentWnd = pTaskbar->GetActiveWindow();
1470 // Raise the current window to the top...
1471 SetWindowPos(currentWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
1472}

Friends And Related Symbol Documentation

◆ DesktopWndProc

LRESULT CALLBACK DesktopWndProc ( HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam )
friend
152{
153
154 switch (message)
155 {
156 //====================
157
158 case BB_RECONFIGURE:
159 case WM_DISPLAYCHANGE:
160 {
161 // Update the desktop's dimensions if the screen resolution changes...
162 pDesktop->GetClockText(true);
165
167 else if (message == WM_DISPLAYCHANGE)
168 {
169 int tempMonitors = GetSystemMetrics(SM_CMONITORS);
170 if (pDesktop->numberOfDisplayMonitors != tempMonitors)
171 {
172 char msg[255];
173 if (tempMonitors > pDesktop->numberOfDisplayMonitors) strcpy(msg, "System -> Display monitor attached.");
174 else if (tempMonitors < pDesktop->numberOfDisplayMonitors) strcpy(msg, "System -> Display monitor removed.");
175 SendMessage(GetBBWnd(), BB_CONSOLEMESSAGE, (WPARAM)CONSOLE_REGULAR_MESSAGE, (LPARAM)msg);
176
177 pDesktop->numberOfDisplayMonitors = tempMonitors;
178 }
179 }
180 break;
181 }
182
183 case WM_SETTINGCHANGE:
184 {
185 if (wParam == SPI_SETWORKAREA)
186 {
187 // Update the desktop's dimensions and position if the work area changes...
188 // (e.g. if the Explorer taskbar is moved to another screen edge)
190
191 // ...and notify plugins that the desktop work area has changed...
192 SendMessage(GetBBWnd(), BB_REDRAWGUI, BBRG_DESKTOP, 0);
193 }
194 return 0;
195 }
196/*
197 case WM_WINDOWPOSCHANGED:
198 {
199 // Move the desktop window back to the bottom of the z-order if its place in it changes...
200// SetWindowPos(pDesktop->hDesktopWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
201// SetWindowPos(pDesktop->hDesktopWnd, GetDesktopWindow(), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
202// SetWindowPos(pDesktop->hDesktopWnd, GetDesktopWindow(), pDesktop->DesktopX, pDesktop->DesktopX, pDesktop->DesktopWidth, pDesktop->DesktopHeight, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
203// SetWindowPos(pDesktop->hDesktopWnd, GetDesktopWindow(), 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOOWNERZORDER);
204 if (pSettings->debugLogging) SendMessage(GetBBWnd(), BB_CONSOLEMESSAGE, (WPARAM)CONSOLE_REGULAR_MESSAGE, (LPARAM)"WM_WINDOWPOSCHANGED");
205// if (pSettings->debugLogging) Log("Desktop: WM_WINDOWPOSCHANGED", "");
206 return 0;
207 }
208*/
209/*
210 case WM_GETMINMAXINFO:
211 {
212 // Not sure if this is really needed since we don't allow the desktop window to be moved/resized anyway, but just in case... ;)
213 MINMAXINFO* mmi = (MINMAXINFO*)lParam;
214 mmi->ptMaxPosition.x = pDesktop->DesktopX;
215 mmi->ptMaxPosition.y = pDesktop->DesktopY;
216 mmi->ptMaxSize.x = pDesktop->DesktopWidth;
217 mmi->ptMaxSize.y = pDesktop->DesktopHeight;
218 return 0;
219 }
220*/
221 //====================
222
223 case WM_TIMER:
224 {
225 // Is it time to update the desktop clock/weekday/date?
227 {
228 if (pDesktop->GetClockText(false))
229 {
230 // Clock timestamp has changed; update the other widgets too, then the Desktop...
233 }
234 }
235 return 0;
236 }
237
238 //====================
239
240 case WM_CLOSE:
241 return 0;
242
243 //====================
244
245 case WM_MOUSEACTIVATE:
246 return MA_NOACTIVATE;
247/*
248 case WM_ACTIVATE:
249 {
250 if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) SetActiveWindow(hwnd);
251 return 0;
252 }
253 break;
254*/
255 //====================
256
257 case WM_NCHITTEST:
258 return HTCLIENT;
259
260 case WM_LBUTTONDOWN:
261 case WM_LBUTTONUP:
262// case WM_LBUTTONDBLCLK:
263 case WM_RBUTTONDOWN:
264 case WM_RBUTTONUP:
265 case WM_MBUTTONDOWN:
266 case WM_MBUTTONUP:
267 case WM_XBUTTONDOWN:
268 case WM_XBUTTONUP:
269 case WM_MOUSEWHEEL:
270 case WM_MOUSEHWHEEL:
271 case WM_DROPFILES:
272 {
273 // First we set focus to the main Blackbox window, in order to prevent the
274 // focus from going back to the previous task after e.g. the menu is closed...
275 SetForegroundWindow(GetBBWnd());
276 pDesktop->MouseAndDropHandler(pDesktop->hDesktopWnd, message, wParam, lParam);
277 return 0;
278 }
279 break;
280
281 //====================
282
283 case BB_WINDOWSHADE:
285 break;
288 break;
291 break;
292 case BB_WINDOWLOWER:
294 break;
295 case BB_WINDOWRAISE:
297 break;
298
299 //====================
300
301 default:
302 return DefWindowProc(hwnd, message, wParam, lParam);
303
304 //====================
305 }
306
307 return 0;
308}
Desktop * pDesktop
Definition Blackbox.cpp:37
#define BB_CONSOLEMESSAGE
Definition BBApi.h:165
#define CONSOLE_REGULAR_MESSAGE
Definition BBApi.h:297
#define BB_REDRAWGUI
Definition BBApi.h:220
#define BB_RECONFIGURE
Definition BBApi.h:147
#define BB_WINDOWSHADE
Definition BBApi.h:202
#define BB_WINDOWGROWHEIGHT
Definition BBApi.h:203
#define BB_WINDOWLOWER
Definition BBApi.h:205
#define BBRG_DESKTOP
Definition BBApi.h:225
#define BB_WINDOWRAISE
Definition BBApi.h:208
#define BB_WINDOWGROWWIDTH
Definition BBApi.h:204
@ SFX_RECONFIGURE
Definition Sounds.h:39
void GrowWindowHeight()
Definition Desktop.cpp:1414
void RaiseWindow()
Definition Desktop.cpp:1467
void LowerWindow()
Definition Desktop.cpp:1443
void GrowWindowWidth()
Definition Desktop.cpp:1427
void ShadeWindow()
Definition Desktop.cpp:1319
LRESULT MouseAndDropHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition Desktop.cpp:1058

Member Data Documentation

◆ hDesktopInstance

HINSTANCE Desktop::hDesktopInstance

◆ hBlackboxWnd

HWND Desktop::hBlackboxWnd

◆ hDesktopWnd

HWND Desktop::hDesktopWnd

◆ cachedBackground

HDC Desktop::cachedBackground

◆ DesktopX

int Desktop::DesktopX

◆ DesktopY

int Desktop::DesktopY

◆ DesktopWidth

int Desktop::DesktopWidth

◆ DesktopHeight

int Desktop::DesktopHeight

◆ DesktopCenterX

int Desktop::DesktopCenterX

◆ DesktopCenterY

int Desktop::DesktopCenterY

◆ CurrentTime

wchar_t Desktop::CurrentTime[32]

◆ CurrentWeekday

wchar_t Desktop::CurrentWeekday[32]

◆ CurrentDate

wchar_t Desktop::CurrentDate[MAX_LINE_LENGTH]

◆ CurrentGreeting

wchar_t Desktop::CurrentGreeting[32]

◆ displayedMinute

int Desktop::displayedMinute

◆ systemTime

time_t Desktop::systemTime

◆ localTime

struct tm Desktop::localTime

◆ currentHour

int Desktop::currentHour

◆ currentMinute

int Desktop::currentMinute

◆ clockRect

RECT Desktop::clockRect

◆ weekdayRect

RECT Desktop::weekdayRect

◆ dateRect

RECT Desktop::dateRect

◆ greetingRect

RECT Desktop::greetingRect

◆ numberOfDisplayMonitors

int Desktop::numberOfDisplayMonitors

◆ wallpaper

WallpaperStruct Desktop::wallpaper