Ask Question

Name:
Title:
Your Question:

Answer Question

Name:
Your Answer:
User Submitted Source Code!


Description:
  gg
Language: C/C++
Code:
/* CmdBkg (c) 2016 Mikael Sollenborn */

#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x0501
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501

// Usage: cmdbkg "file.bmp" [transparency 0-100(default 33) [includeBorders]]
// Specify no arguments to remove previous background. 
// Specify /? as first argument to see this help.

// Compilation: gcc -o cmdbkg.exe cmdbkg.c -lgdi32 -ldwmapi -mwindows

// TODO/Issues:
// 1. Allow centered placement of image, no stretching?
// 2. Background window visible a short time after restoring minimized console window. Minimize background if console window is minimized?
// 3. Inelegant polling. Use SetWinEventHook instead?
// 4. Find a better way to kill the old background window than this horrible title polling hack
// 5. Program blocks if run from a batch script, need to use: start "" cmdbkg

#include <windows.h>
#include <stdio.h>
#include <dwmapi.h>
#include <TlHelp32.h>

#define POLL_INTERVAL 20
#define KILL_TITLE_MESSAGE L"Kill"

// Functions Fn_LoadBmp and f_SetConsoleTransparency by user "aGerman" at dostips.com

int Fn_LoadBmp(HWND hWnd, wchar_t *szBmpPath, long x, long y, long z, long w, long h)
{
     HDC hDc = NULL, hDcBmp = NULL;
      HBITMAP hBmp1 = NULL, hBmp2 = NULL;
     HGDIOBJ hGdiObj = NULL;
     BITMAP bmp = {0};
     int iRet = EXIT_FAILURE;

     if (hWnd)
     {
          if ((hDc = GetDC(hWnd)))
          {
               if ((hDcBmp = CreateCompatibleDC(hDc)))
               {
                    if ((hBmp1 = (HBITMAP)LoadImage(NULL, szBmpPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)))
                    {
                         if (GetObject(hBmp1, sizeof(bmp), &bmp))
                         {
                              if (w == -1) {
                                   if ((w = bmp.bmWidth * z / 100.0 + 0.5) <= 0 || (h = bmp.bmHeight * z / 100.0 + 0.5) <= 0)
                                   {
                                        w = bmp.bmWidth;
                                        h = bmp.bmHeight;
                                   }
                              }
                              if ((hBmp2 = (HBITMAP)CopyImage((HANDLE)hBmp1, IMAGE_BITMAP, w, h, LR_COPYDELETEORG)))
                              {
                                   if ((hGdiObj = SelectObject(hDcBmp, hBmp2)) && hGdiObj != HGDI_ERROR)
                                   {
                                        // iRet = EXIT_SUCCESS; // ugly fix of BitBlt fail when changing user
                                        if (BitBlt(hDc, (int)x, (int)y, (int)w, (int)h, hDcBmp, 0, 0, SRCCOPY))
                                             iRet = EXIT_SUCCESS;
                                        DeleteObject(hGdiObj);
                                   }
                                   DeleteObject(hBmp2);
                              }
                         }
                         DeleteObject(hBmp1);
                    }
                    ReleaseDC(hWnd, hDcBmp);
               } 
               ReleaseDC(hWnd, hDc);
          }
     }
     return iRet;
}

BOOL f_SetConsoleTransparency(HWND hConsoleWnd, long percentage)
{
     BYTE bAlpha = 0;
     LONG lNewLong = 0;
     if (hConsoleWnd && percentage > -1 && percentage < 101)
     {
          bAlpha = (BYTE)(2.55 * (100 - percentage) + 0.5);
          lNewLong = GetWindowLong(hConsoleWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
          if (!SetWindowLong(hConsoleWnd, GWL_EXSTYLE, lNewLong)) return FALSE;
          return SetLayeredWindowAttributes(hConsoleWnd, 0, bAlpha, LWA_ALPHA);
     }
     return FALSE;
}


DWORD getParentPID(DWORD pid)
{
     HANDLE h = NULL;
     PROCESSENTRY32 pe = { 0 };
     DWORD ppid = 0;
     pe.dwSize = sizeof(PROCESSENTRY32);
     h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     if( Process32First(h, &pe)) 
     {
          do 
          {
               if (pe.th32ProcessID == pid) 
               {
                    ppid = pe.th32ParentProcessID;
                    break;
               }
          } while( Process32Next(h, &pe));
     }
     CloseHandle(h);
     return (ppid);
}

HWND FindTopMostWindow(DWORD dwProcID)
{
     HWND hWnd = GetTopWindow(GetDesktopWindow());
     while(hWnd)
     {
          DWORD dwWndProcID = 0;
          GetWindowThreadProcessId(hWnd, &dwWndProcID);
          if(dwWndProcID == dwProcID)
               return hWnd;            
          hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
     }
     return NULL;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
     int bx, by, bw, bh, ret;
     int nbx, nby, nbw, nbh, w, h;
     int fw = 0, fh = 0, fth = 0;
     HWND hConsoleWnd, hBkgWnd, currFgWnd, tempWnd;
     RECT bounds, extendBounds;
     LPWSTR *szArgList;
     int argCount, initialRedraw = 10, compTitle = 1, transparency = 33;
     wchar_t titleBuffer[1024];
     WNDCLASS wc={0};
     UINT_PTR timerId;
     BOOL bIsWeirdoBorders = FALSE;
     BOOL res;
     MSG msg;
     DWORD parentPID;

     /*
     if (AttachConsole(ATTACH_PARENT_PROCESS)) { // easier method, and working
          hConsoleWnd = GetConsoleWindow();
          FreeConsole();
     } */
     
//          hConsoleWnd = GetForegroundWindow(); // too unreliable
     parentPID = getParentPID( GetCurrentProcessId());
     hConsoleWnd = FindTopMostWindow(parentPID);

     if (hConsoleWnd) {
          GetWindowRect(hConsoleWnd, &bounds);
          bx = bounds.left;
          by = bounds.top;
          bw = bounds.right-bounds.left;
          bh = bounds.bottom-bounds.top;
     } else {
          MessageBox(NULL, L"Unable to prepare window creation", L"Error", MB_OK);
          return 1;
     }

     DwmGetWindowAttribute(hConsoleWnd, DWMWA_EXTENDED_FRAME_BOUNDS, &extendBounds, sizeof(extendBounds));
     if (extendBounds.left != bounds.left) bIsWeirdoBorders = TRUE;
     
     szArgList = CommandLineToArgvW(GetCommandLine(), &argCount);
     if (szArgList == NULL)
     {
          MessageBox(NULL, L"Unable to get arguments", L"Error", MB_OK);
          return 1;
     }
     
     if (argCount == 2 && wcscmp(szArgList[1], L"/?") == 0) {
          MessageBox(NULL, L"Usage: cmdbkg "file.bmp" [transparency 0-100(default 33) [includeBorders]]nnSpecify no arguments to remove previous background.nn(C)opyright 2016 Mikael Sollenborn", L"CmdBkg Arguments", MB_OK); 
          return 0;
     }

     f_SetConsoleTransparency(hConsoleWnd, 0);

     GetWindowText(hConsoleWnd, titleBuffer, 1023);
     SetWindowText(hConsoleWnd, KILL_TITLE_MESSAGE);
     Sleep(500);
     SetWindowText(hConsoleWnd, titleBuffer);
     
     if (argCount < 2) {
          f_SetConsoleTransparency(hConsoleWnd, 0);
          return 0;
     }
     
     if (argCount > 2) {
          transparency = wcstol (szArgList[2], NULL, 10);
     }

     if (argCount <= 3 || (argCount > 3 && bIsWeirdoBorders)) {
          fw = GetSystemMetrics(SM_CXSIZEFRAME);
          if(argCount <= 3) fth = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
          fh = fth + GetSystemMetrics(SM_CYSIZEFRAME);
     }

     w = nbw-fw*2, h = nbh-fth;
     if (w < 1) w = 1;
     if (h < 1) h = 1;
     
     wc.lpszClassName=L"CmdBkgWindowBackground";
     wc.lpfnWndProc=DefWindowProc; // Use default Window proc
     wc.hInstance=hInstance;
     wc.hbrBackground=(HBRUSH)(COLOR_3DFACE+1);
     wc.hCursor=LoadCursor(NULL,IDC_ARROW);
     if (!RegisterClass(&wc)) { MessageBox(NULL, L"Unable to prepare window creation", L"Error", MB_OK); LocalFree(szArgList); return 1; }
     hBkgWnd=CreateWindowEx(0,wc.lpszClassName,0,WS_POPUP|WS_VISIBLE,bx+fw,by+fth,w,h,0,0,0,0);
     if (!hBkgWnd) { MessageBox(NULL, L"Unable to create background window", L"Error", MB_OK); LocalFree(szArgList); return 1; }

     ret = Fn_LoadBmp(hBkgWnd, szArgList[1], 0, 0, 100, w, h);
     if (ret == EXIT_FAILURE) { std::cout << "Hello, World!n"; LocalFree(szArgList); return 1; }

     f_SetConsoleTransparency(hConsoleWnd, transparency);
     
     ShowWindow(hBkgWnd, SW_HIDE);
     SetWindowLongPtr(hBkgWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
     ShowWindow(hBkgWnd, SW_SHOW);
     
     SetForegroundWindow(hConsoleWnd);

     currFgWnd = GetForegroundWindow();
     
//     while((IsWindow(hConsoleWnd) || IsIconic(hConsoleWnd)) && ret == EXIT_SUCCESS && compTitle != 0) {
     while((IsWindow(hConsoleWnd) || IsIconic(hConsoleWnd)) && compTitle != 0) {
          timerId = SetTimer(NULL, 0, POLL_INTERVAL, NULL);
          res = GetMessage(&msg,0,0,0);
          KillTimer(NULL, timerId);
          
          if (!(res && msg.message == WM_TIMER && msg.hwnd == NULL && msg.wParam == timerId)) {
               DispatchMessage(&msg);
          }
          
          GetWindowText(hConsoleWnd, titleBuffer, 1023);
          compTitle = wcscmp(titleBuffer, KILL_TITLE_MESSAGE);
          
          GetWindowRect(hConsoleWnd, &bounds);
          nbx = bounds.left;
          nby = bounds.top;
          nbw = bounds.right-bounds.left;
          nbh = bounds.bottom-bounds.top;

          tempWnd = GetForegroundWindow();
          if (currFgWnd != tempWnd) {
               if (initialRedraw < 5) initialRedraw = 5;
               currFgWnd = tempWnd;
          }

          SetWindowPos(hBkgWnd, hConsoleWnd, nbx+fw, nby+fth, nbw-fw*2, nbh-fh, SWP_SHOWWINDOW);
          if (initialRedraw > 0 || nbx != bx || nby != by || nbw != bw || nbh != bh) {
               w = nbw-fw*2, h = nbh-fth;
               if (w < 1) w = 1;
               if (h < 1) h = 1;
               ret = Fn_LoadBmp(hBkgWnd, szArgList[1], 0, 0, 100, w, h);
               bx = nbx; by = nby; bw = nbw; bh = nbh;
               if (initialRedraw > 0) initialRedraw--;
          }
     }
     
     LocalFree(szArgList);
     return 0;
}

          
Comments: