cs_rt15
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
1 déc. 2008 à 20:46
Quelques éssais sur le sujet. Après l'exécutable encapsulé est plus ou moins consentant... Ici je tente d'encapsuler la calculatrice. Elle a la facheuse tendance à s'afficher même démarrée en SW_HIDE. Le premier refresh n'est aussi pas très propre... Sortir la fenêtre de l'écran pour la forcer à se redessiner. Notepad et mspaint donne de bons résultats.
Attention : risque de boucle infini lors de recherche de la fenêtre de l'application lancée. Déjà, ajouter un test WaitForSingleObject (De 0) sur le processus peut bien limiter les risques (Sortie de boucle si le processus crève).
Application complète, unicode ou non, compilation testée sous VC6 et gcc (Code::Blocks).
<hr size="2" width="100%" />#define UNICODE
/*
Pour compiler sous gcc en release, ajouter :
-nostartfiles -nodefaultlibs -nostdlib
dans les options du lieur.
*/
/* Suppression de la CRT sous VC */
#ifdef NDEBUG
#pragma comment(linker, "/NODEFAULTLIB")
#endif
/* Gestion de la compilation en unicode */
#ifdef UNICODE
#define _T(x) L ## x
typedef unsigned short TCHAR;
#else
#define _T(x) x
typedef char TCHAR;
#endif
#include "windows.h"
HINSTANCE _hThisInstance; /* Handle du module */
HWND _hWnd; /* Handle de la fenêtre */
HWND _hCalcHwnd; /* Handle de la fenêtre de calc */
DWORD _nCalcPid; /* PID de la calculatrice */
TCHAR* _lpAppName = _T("Embedded calc"); /* Nom de l'appli */
/**
* Affiche le message d'erreur associé à la dernière erreur Win32
*
* @return Le code de la dernière erreur
*/
DWORD __stdcall ShowLastError()
{
DWORD nLastError; /* Code de la dernière erreur */
TCHAR* lpMessageBuffer; /* Message d'erreur associé */
/* Récupération du numéro de l'erreur */
nLastError = GetLastError();
/* Formatage du message */
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMessageBuffer, 0, NULL);
/* Affichage du message */
MessageBox(NULL, lpMessageBuffer, _T("ERROR"), MB_OK | MB_ICONERROR);
return nLastError;
}
/**
* Traitement des messages
*/
LRESULT __stdcall WindowProcedure(HWND hWnd, UINT nMessage,
WPARAM wParam, LPARAM lParam)
{
switch (nMessage)
{
case WM_DESTROY:
/* On signale que le thread va s'arrêter */
PostQuitMessage(0);
break;
default:
/* Application du traitement par défaut */
return DefWindowProc(hWnd, nMessage, wParam, lParam);
}
return 0;
}
/**
* Initialise la fenêtre principale de l'appli
*/
void __stdcall InitWindow()
{
WNDCLASSEX wincl; /* Classe de la fenêtre utilisée */
/* Création de la classe de fenêtre */
wincl.cbSize = sizeof(WNDCLASSEX);
wincl.style = 0;
wincl.lpfnWndProc = WindowProcedure;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hInstance = _hThisInstance;
wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wincl.lpszMenuName = NULL;
wincl.lpszClassName = _lpAppName;
wincl.hIconSm = NULL;
/* Enregistrement de la classe */
if (RegisterClassEx(&wincl) == 0)
ExitProcess(ShowLastError());
/* Création de la fenêtre */
_hWnd = CreateWindowEx(0, _lpAppName, _lpAppName,
WS_OVERLAPPED | WS_SYSMENU |
WS_MINIMIZEBOX | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
600, 400,
HWND_DESKTOP, NULL, _hThisInstance, NULL);
if (_hWnd == 0)
ExitProcess(ShowLastError());
}
/**
* Callback d'énumération des fenêtre pour trouver celle de la calculatrice
*/
BOOL __stdcall RetrieveCalcWindow(HWND hwnd, LPARAM lParam)
{
DWORD nPid; /* Récupération du PID associé à la fenêtre */
BOOL bFound; /* Fenêtre trouvée ? */
GetWindowThreadProcessId(hwnd, &nPid);
if (nPid == _nCalcPid)
{
_hCalcHwnd = hwnd;
bFound = TRUE;
}
else
bFound = FALSE;
/* On arrête l'énumération si on a trouvé */
return ! bFound;
}
/**
* Met une calculatrice dans la fenêtre
*/
void __stdcall EmbedCalc()
{
STARTUPINFO startupInfo; /* Configuration du démarrage */
PROCESS_INFORMATION processInfo; /* Informations sur le processus */
char* lpInfos; /* Nettoyage de startupInfo */
TCHAR lpCommandLine[20]; /* Pour l'unicode */
DWORD nI;
/* Nettoyage de startupInfo */
lpInfos = (char*)&startupInfo;
for (nI = 0; nI < sizeof(STARTUPINFO); nI++)
{
*lpInfos = 0;
lpInfos++;
}
/* Initialisation de startupInfo */
startupInfo.cb = sizeof(STARTUPINFO);
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_HIDE;
/* La ligne de commande doit être modifiable en unicode */
lstrcpy(lpCommandLine, _T("calc"));
/* Lancement de la calculatrice */
if (CreateProcess(NULL, lpCommandLine, NULL, NULL,
FALSE, CREATE_DEFAULT_ERROR_MODE,
NULL, NULL, &startupInfo, &processInfo) == 0)
ExitProcess(ShowLastError());
Sleep(2000);
/* Fermeture des handles inutiles */
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
_hCalcHwnd = 0;
_nCalcPid = processInfo.dwProcessId;
/* Récupération d'un handle sur la fenêtre de la calculatrice */
while (_hCalcHwnd == 0)
{
EnumWindows(RetrieveCalcWindow, 0);
Sleep(1);
}
/* Affectation du style de la calculatrice */
SetWindowLong(_hCalcHwnd, GWL_STYLE, WS_CHILD);
/* Mise en place de la calculatrice dans notre fenêtre */
SetParent(_hCalcHwnd, _hWnd);
/* On réaffiche dans notre fenêtre */
SetWindowPos(_hCalcHwnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
ShowWindow(_hCalcHwnd, SW_SHOW);
RedrawWindow(_hWnd, NULL, NULL, RDW_INVALIDATE);
}
/**
* Point d'entrée du programme
*
* @return Code d'erreur du processus
*/
#ifdef NDEBUG
int __cdecl WinMainCRTStartup()
#else
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
#endif
{
MSG messages; /* Réception des messages envoyés à l'application */
/* Récupération du handle du module */
_hThisInstance = GetModuleHandle(NULL);
InitWindow();
EmbedCalc();
/* Boucle de traitement des messages */
while (GetMessage(&messages, NULL, 0, 0))
{
/* Traduit certains messages */
TranslateMessage(&messages);
/* Distribution des messages aux fenêtres */
DispatchMessage(&messages);
}
/* Code d'erreur en sortie */
return messages.wParam;
}