Click to See Complete Forum and Search --> : Window embedded directly to the desktop?


OpisCossack
October 13th, 2008, 05:07 AM
Hey guys, first post in this forum :)

I'm trying to set a window directly onto the desktop, so that clicking the "Show Desktop" shell command wouldn't make it dissapear, here's what I've go so far:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "resources/resources.h"

LRESULT CALLBACK window_process (HWND, UINT, WPARAM, LPARAM);
void error(char * from);
int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance,
PSTR cmd_line, int cmd_show){
HWND hwnd;
MSG window_msg;
WNDCLASS mainwnd;

memset(&mainwnd, 0, sizeof(WNDCLASS));
mainwnd.style = CS_HREDRAW | CS_VREDRAW ;
mainwnd.lpfnWndProc = &window_process;
mainwnd.cbClsExtra = 0;
mainwnd.cbWndExtra = 0;
mainwnd.hInstance = instance;
mainwnd.hIcon = LoadIcon (NULL, IDI_APPLICATION);
mainwnd.hCursor = LoadCursor (NULL, IDC_ARROW); // default IDC_ARROW
mainwnd.hbrBackground = CreateSolidBrush(RGB(250,250,250));
mainwnd.lpszClassName = app_name;
mainwnd.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);

if(!RegisterClass(&mainwnd)){
error("RegisterClass");
return 0;
}
hwnd = CreateWindow(app_name, app_name,WS_POPUP,
500, 500, 500, 200, NULL,
NULL, instance, NULL);

if(!hwnd){
error("hwnd");
}

ShowWindow (hwnd, cmd_show);
UpdateWindow(hwnd);

while(GetMessage (&window_msg, NULL, 0, 0)){
TranslateMessage(&window_msg);
DispatchMessage(&window_msg);
}

return window_msg.wParam;
}

LRESULT CALLBACK window_process (HWND hwnd, UINT message, WPARAM
wParam, LPARAM lParam){
HDC hdc;
PAINTSTRUCT paint_class;
RECT rect;
long style;
if(message == WM_PAINT){
hdc = BeginPaint(hwnd, &paint_class);
GetClientRect(hwnd, &rect);
EndPaint (hwnd, &paint_class);
}
else if(message == WM_COMMAND){
switch(LOWORD(wParam)){
case ID_FILE_EXIT:
exit(1);
break;
}
}
else if(message == WM_ACTIVATE){
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
SetParent(hwnd, GetDesktopWindow());

GetWindowLong(hwnd, GWL_STYLE);
style = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, style | WS_CHILD);
}
else if(message == WM_DESTROY){
PostQuitMessage(0);
return 0;
}
else if(message == WM_CLOSE){
DestroyWindow(hwnd);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

void error(char * from){
char formulated[512];
char printed[560];
memset(formulated, 0, 512);
memset(printed, 0, 560);

FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0,
formulated, 511, NULL);
sprintf(printed, "A fatal %s error has occured: %s", from, formulated);
MessageBox (NULL, printed, app_name, MB_ICONERROR);
exit(1);
}


However, this has a few problems, clicking the "Show Desktop" shell command will not show the window, it flickers when you click the menu, and other display problems.

If anyone has any ideas on how to do this, it'd be greatly appreicated, thanks.

JohnCz
October 13th, 2008, 10:08 PM
You would be better off making main window owned by the top desk top window.
You will have to use system tray to bring it up front.

Window has window procedure that processes messages. It is not a window process.
// DesktopHideImmune.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "DesktopHideImmune.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_DESKTOPHIDEIMMUNE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DESKTOPHIDEIMMUNE));

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}



//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DESKTOPHIDEIMMUNE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DESKTOPHIDEIMMUNE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // Store instance handle in our global variable

HWND hDeskWnd = FindWindow(_T("Progman"), NULL);
if(NULL == hDeskWnd)
{
return FALSE;
}

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hDeskWnd, NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

OpisCossack
October 23rd, 2008, 12:43 AM
Well alright, that wasn't exactly what I was looking for.

However, I've found a solution incase anyone's interested, this will create the lowest-level window possible:


int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance,
PSTR cmd_line, int cmd_show){
// Do the window registeration, bla bla bla
HWND hwnd;
MSG window_msg;
WNDCLASS mainwnd;

memset(&mainwnd, 0, sizeof(WNDCLASS));
mainwnd.style = CS_HREDRAW | CS_VREDRAW ;
mainwnd.lpfnWndProc = &window_process;
mainwnd.cbClsExtra = 0;
mainwnd.cbWndExtra = 0;
mainwnd.hInstance = instance;
mainwnd.hIcon = LoadIcon(instance, "ICON_OPEN");
mainwnd.hCursor = LoadCursor (NULL, IDC_ARROW); // default IDC_ARROW
mainwnd.hbrBackground = CreateSolidBrush(RGB(21,21,21));
mainwnd.lpszClassName = app_name;
mainwnd.lpszMenuName = NULL;

if(!RegisterClass(&mainwnd)){
error("RegisterClass");
}

HWND hdesk = GetDesktopWindow(); // now get the desktop handle
hwnd = CreateWindow(app_name, app_name, WS_POPUP | WS_VSCROLL,
user_config.pos_x, user_config.pos_y, user_config.width,
user_config.height, hdesk, NULL, instance, NULL);
SetScrollRange (hwnd, SB_VERT, 1, 3, TRUE); // create the window, make sure its set as a child window to the desktop handle

if(!hwnd){
error("from:CreateWindow");
}

HWND hprogman = FindWindow("Progman","Program Manager"); // now set it as a child to the window manager of XP
if (hprogman == NULL){
hprogman = FindWindow("#32769",""); // this is for Vista compatibility
}
SetParent(hwnd, hprogman); // set it
SetWindowLong(hwnd, GWL_STYLE, (GetWindowLong(hwnd, GWL_STYLE) | WS_CHILD));

ShowWindow (hwnd, cmd_show);
UpdateWindow(hwnd);

while(GetMessage (&window_msg, NULL, 0, 0)){
TranslateMessage(&window_msg);
DispatchMessage(&window_msg);
}
// rest follows


And voila, desktop embedded window, thanks for your input John, appreicate it.