#include "resource.h" /*variables*/ UINT WM_TASKBAR = 0; HWND Hwnd; HMENU Hmenu; NOTIFYICONDATA notifyIconData; TCHAR szTIP[64] = TEXT("Snoopy.. \n Kicks Ass!"); const wchar_t* szClassName = L"Snoopy's System Tray Demo."; /*procedures */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); void minimize(); void restore(); void InitNotifyIconData(); int CaptureImage(HWND hWnd, const wchar_t* filename); int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ WM_TASKBAR = RegisterWindowMessageA("TaskbarCreated"); /* The Window structure */ wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); /* Use default icon and mouse-pointer */ wincl.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(ICO1)); wincl.hIconSm = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(ICO1)); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ wincl.hbrBackground = (HBRUSH)(CreateSolidBrush(RGB(255, 255, 255))); /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ Hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ szClassName, /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 544, /* The programs width */ 375, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /*Initialize the NOTIFYICONDATA structure only once*/ InitNotifyIconData(); /* Make the window visible on the screen */ ShowWindow (Hwnd, nCmdShow); /* register hotkey. 0x59 is 'y' so win+y or print * * see: https://docs.microsoft.com/de-de/windows/desktop/inputdev/virtual-key-codes */ if (!RegisterHotKey(Hwnd, WM_HOTKEY_FREEZE, MOD_WIN, 0x59) || !RegisterHotKey(Hwnd, WM_HOTKEY_FREEZE, 0, 0x2c)) { FatalAppExit(0, TEXT("Couldn't register hotkey!")); } /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } // clean up here? return messages.wParam; } /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if ( message==WM_TASKBAR && !IsWindowVisible( Hwnd ) ) { minimize(); return 0; } switch (message) /* handle the messages */ { case WM_ACTIVATE: Shell_NotifyIcon(NIM_ADD, ¬ifyIconData); break; case WM_CREATE: ShowWindow(Hwnd, SW_HIDE); Hmenu = CreatePopupMenu(); AppendMenu(Hmenu, MF_STRING, ID_TRAY_EXIT, TEXT( "Exit The Demo" ) ); break; case WM_SYSCOMMAND: /*In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.*/ switch( wParam & 0xFFF0 ) { case SC_MINIMIZE: case SC_CLOSE: minimize() ; return 0 ; break; } break; // Our user defined WM_SYSICON message. case WM_SYSICON: { switch(wParam) { case ID_TRAY_APP_ICON: SetForegroundWindow(Hwnd); break; } if (lParam == WM_LBUTTONUP) { restore(); } else if (lParam == WM_RBUTTONDOWN) { // Get current mouse position. POINT curPoint ; GetCursorPos( &curPoint ) ; SetForegroundWindow(Hwnd); // TrackPopupMenu blocks the app until TrackPopupMenu returns UINT clicked = TrackPopupMenu(Hmenu,TPM_RETURNCMD | TPM_NONOTIFY,curPoint.x,curPoint.y,0,hwnd,NULL); SendMessage(hwnd, WM_NULL, 0, 0); // send benign message to window to make sure the menu goes away. if (clicked == ID_TRAY_EXIT) { // quit the application. Shell_NotifyIcon(NIM_DELETE, ¬ifyIconData); UnregisterHotKey(Hwnd, WM_HOTKEY_FREEZE); PostQuitMessage( 0 ) ; } } } break; case WM_HOTKEY_FREEZE: { restore(); } break; // intercept the hittest message.. case WM_NCHITTEST: { UINT uHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam); if(uHitTest == HTCLIENT) return HTCAPTION; else return uHitTest; } case WM_CLOSE: minimize() ; return 0; break; case WM_DESTROY: PostQuitMessage (0); break; } return DefWindowProc( hwnd, message, wParam, lParam ) ; } void minimize() { // hide the main window ShowWindow(Hwnd, SW_HIDE); } void restore() { ShowWindow(Hwnd, SW_SHOW); CaptureImage(Hwnd, L"file.bmp"); } void InitNotifyIconData() { memset( ¬ifyIconData, 0, sizeof( NOTIFYICONDATA ) ) ; notifyIconData.cbSize = sizeof(NOTIFYICONDATA); notifyIconData.hWnd = Hwnd; notifyIconData.uID = ID_TRAY_APP_ICON; notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; notifyIconData.uCallbackMessage = WM_SYSICON; //Set up our invented Windows Message notifyIconData.hIcon = (HICON)LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE(ICO1) ) ; wcsncpy(notifyIconData.szTip, szTIP, sizeof(szTIP)); } void getRaspiStorage() { // GetLogicalDrives() // for result // if result.GetDriveType() == DRIVE_REMOVABLE TCHAR szName[MAX_PATH]; TCHAR szTemp[512]; TCHAR szDrive[3] = TEXT(" :"); szTemp[0] = '\0'; if (GetLogicalDriveStrings(BUFSIZE-1, szTemp)) { BOOL bFound = FALSE; for (TCHAR* p = szTemp; !bFound && *p; *p++;) { *szDrive = *p; if (QueryDosDevice(szDrive, szName, MAX_PATH)) { } } } } // FUNCTION: CaptureAnImage(HWND hWnd) // // PURPOSE: Captures a screenshot into a window and then saves it in a .bmp file. // // COMMENTS: // // Note: This sample will attempt to create a file called captureqwsx.bmp // // https://docs.microsoft.com/de-de/windows/desktop/gdi/capturing-an-image int CaptureImage(HWND hWnd, const wchar_t* filename) { HDC hdcScreen; HDC hdcWindow; HDC hdcMemDC = NULL; HBITMAP hbmScreen = NULL; BITMAP bmpScreen; // Retrieve the handle to a display device context for the client // area of the window. hdcScreen = GetDC(NULL); hdcWindow = GetDC(hWnd); // Create a compatible DC which is used in a BitBlt from the window DC hdcMemDC = CreateCompatibleDC(hdcWindow); if(!hdcMemDC) { MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK); DeleteObject(hdcMemDC); ReleaseDC(NULL,hdcScreen); ReleaseDC(hWnd,hdcWindow); return -1; } // Get the client area for size calculation RECT rcClient; GetClientRect(hWnd, &rcClient); //This is the best stretch mode SetStretchBltMode(hdcWindow,HALFTONE); //The source DC is the entire screen and the destination DC is the current window (HWND) if(!StretchBlt(hdcWindow, 0,0, rcClient.right, rcClient.bottom, hdcScreen, 0,0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), SRCCOPY)) { MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK); DeleteObject(hdcMemDC); ReleaseDC(NULL,hdcScreen); ReleaseDC(hWnd,hdcWindow); return -1; } // Create a compatible bitmap from the Window DC hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top); if(!hbmScreen) { MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK); DeleteObject(hbmScreen); DeleteObject(hdcMemDC); ReleaseDC(NULL,hdcScreen); ReleaseDC(hWnd,hdcWindow); return -1; } // Select the compatible bitmap into the compatible memory DC. SelectObject(hdcMemDC,hbmScreen); // Bit block transfer into our compatible memory DC. if(!BitBlt(hdcMemDC, 0,0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, hdcWindow, 0,0, SRCCOPY)) { MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK); DeleteObject(hbmScreen); DeleteObject(hdcMemDC); ReleaseDC(NULL,hdcScreen); ReleaseDC(hWnd,hdcWindow); return -1; } // Get the BITMAP from the HBITMAP GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen); BITMAPFILEHEADER bmfHeader; BITMAPINFOHEADER bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bmpScreen.bmWidth; bi.biHeight = bmpScreen.bmHeight; bi.biPlanes = 1; bi.biBitCount = 32; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight; // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc // have greater overhead than HeapAlloc. HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); char *lpbitmap = (char *)GlobalLock(hDIB); // Gets the "bits" from the bitmap and copies them into a buffer // which is pointed to by lpbitmap. GetDIBits(hdcWindow, hbmScreen, 0, (UINT)bmpScreen.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS); // A file is created, this is where we will save the screen capture. HANDLE hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // Add the size of the headers to the size of the bitmap to get the total file size DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //Offset to where the actual bitmap bits start. bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); //Size of the file bmfHeader.bfSize = dwSizeofDIB; //bfType must always be BM for Bitmaps bmfHeader.bfType = 0x4D42; //BM DWORD dwBytesWritten = 0; WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL); //Unlock and Free the DIB from the heap GlobalUnlock(hDIB); GlobalFree(hDIB); //Close the handle for the file that was created CloseHandle(hFile); return 0; }