mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3811 lines
104 KiB
3811 lines
104 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: topdesk.c - TopDesk application
|
|
*
|
|
* Copyright (c) 1992 Sanford Staab
|
|
*
|
|
\***************************************************************************/
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
#define NOGDICAPMASKS
|
|
#define NOATOM
|
|
#define NOCLIPBOARD
|
|
#define NOLOGERROR
|
|
#define NOMETAFILE
|
|
#define NOOEMRESOURCE
|
|
#define NOSCROLL
|
|
#define NOPROFILER
|
|
#define NODRIVERS
|
|
#define NOCOMM
|
|
#define NODBCS
|
|
#define NOSYSTEMPARAMSINFO
|
|
#define NOSCALABLEFONT
|
|
|
|
//#define DEBUG
|
|
|
|
#include "topdesk.h"
|
|
//#include <shell.h> // import stuff directly-------------------------
|
|
HINSTANCE RealShellExecuteA(
|
|
HWND hwndParent,
|
|
LPCSTR lpOperation,
|
|
LPCSTR lpFile,
|
|
LPCSTR lpParameters,
|
|
LPCSTR lpDirectory,
|
|
LPSTR lpResult,
|
|
LPCSTR lpTitle,
|
|
LPSTR lpReserved,
|
|
WORD nShow,
|
|
LPHANDLE lphProcess);
|
|
|
|
HINSTANCE RealShellExecuteW(
|
|
HWND hwndParent,
|
|
LPCWSTR lpOperation,
|
|
LPCWSTR lpFile,
|
|
LPCWSTR lpParameters,
|
|
LPCWSTR lpDirectory,
|
|
LPWSTR lpResult,
|
|
LPCWSTR lpTitle,
|
|
LPWSTR lpReserved,
|
|
WORD nShow,
|
|
LPHANDLE lphProcess);
|
|
|
|
#ifndef UNICODE
|
|
#define RealShellExecute RealShellExecuteA
|
|
#else
|
|
#define RealShellExecute RealShellExecuteW
|
|
#endif //UNICODE
|
|
//--------------------------------------------------------------------
|
|
#include "itsybits.h" // tiny caption module
|
|
|
|
#define CondDefWindowProc(h, m, w, l) (pro.fShowFrameCtrls ? DefWindowProc(h, m, w, l) : ibDefWindowProc(h, m, w, l))
|
|
#ifndef HLOCAL
|
|
#define HLOCAL HANDLE
|
|
#endif /* HLOCAL */
|
|
|
|
#ifndef MAX_PATH
|
|
#define MAX_PATH 128
|
|
#endif
|
|
|
|
/* --------------------- How the dang thing works -----------------------
|
|
|
|
magnification factor (0 = highest magnification)( mfx , mfy )
|
|
number of virtual desktops showing ( nxVDT , nyVDT )
|
|
Real Desktop size == screen size ( cxrDT , cyrDT )
|
|
client window size ( cxc , cyc )
|
|
Client coords Desktop size ( cxcDT , cycDT )
|
|
offset of home desktop from center VDT org ( oxrHDT , oyrHDT )
|
|
offset of current desktop from center VDT org ( oxrCDT , oyrCDT )
|
|
origin of center VDT in client coords ( oxcODT , oycODT )
|
|
|
|
relations: ? = x or y Dependent vars
|
|
|
|
To find out how many VDTs fit in the client:
|
|
n?VDT = mf? << 1 + 1 mf?
|
|
To find size of the desktop on the client:
|
|
c?cDT = (c?c + (n?VDT / 2)) / n?VDT mf?, c?c
|
|
To find the origin of the desktop on the client:
|
|
o?cODT = c?cDT * mf? mf?, c?cDT
|
|
o?rCDT is (0,0) when in relative viewing mode
|
|
o?rHDT is (0,0) when in absolute viewing mode
|
|
real -> client coord conversion:
|
|
?c = ((?r + o?rCDT) * (c?cDT / c?rDT) + o?cODT
|
|
client -> real coord conversion:
|
|
?r = ((?c - o?cODT) * (c?rDT / c?cDT) - o?rCDT
|
|
|
|
------------------------------------------------------------------------*/
|
|
|
|
// Globals
|
|
|
|
#ifdef DEBUG
|
|
FILE *hfDbgOut;
|
|
#define DPRINTF(x) fprintf##x;
|
|
#else
|
|
#define DPRINTF(x)
|
|
#endif // DEBUG
|
|
BOOL fStartingGhost = FALSE;
|
|
BOOL fBlockRefresh = FALSE;
|
|
BOOL fFrameToggleSize = FALSE;
|
|
BOOL fInvalidated = FALSE;
|
|
BOOL fStarted = FALSE;
|
|
BOOL fCairoShell = FALSE;
|
|
LPTSTR pszTopmost;
|
|
LPTSTR pszShowFrmCtrls;
|
|
LPTSTR pszData;
|
|
LPTSTR pszTopdeskHelpTitle;
|
|
LPTSTR pszHelpFileName;
|
|
LPTSTR pszWorking;
|
|
LPTSTR pszProfile;
|
|
LPTSTR pszStartupInfo;
|
|
LPTSTR pszTitle;
|
|
LPTSTR pszSubKey;
|
|
LPTSTR pszVersion;
|
|
TCHAR szWindowsDir[_MAX_PATH];
|
|
TCHAR szColorName[MAX_COLORNAME];
|
|
TCHAR szResString2[MAX_RESSTRING];
|
|
TCHAR szResString[MAX_RESSTRING];
|
|
LPTSTR pszSetTitle;
|
|
FARPROC fpRefreshEnumProc;
|
|
HANDLE hAccel;
|
|
HANDLE hInst;
|
|
HBITMAP hbmMem;
|
|
HBITMAP hbmOldMem;
|
|
HDC hdcDraw;
|
|
HDC hdcMem;
|
|
HFONT hMyFont;
|
|
HKEY hKeyTopDesk = NULL;
|
|
HWND hwndDT = 0;
|
|
HWND hwndFocus = 0;
|
|
HWND hwndTopdesk;
|
|
INT iStartGhost = -1;
|
|
INT cGhosts = 0;
|
|
INT cWindows = 0;
|
|
INT cxc;
|
|
INT cxcDT;
|
|
INT cxcDTmin;
|
|
INT cxFrame;
|
|
INT cxrDT;
|
|
INT cyc;
|
|
INT cycDT;
|
|
INT cycDTmin;
|
|
INT cyFrame;
|
|
INT cyrDT;
|
|
INT iRefresh;
|
|
INT ihwndJump = -1;
|
|
INT nxVDT;
|
|
INT nyVDT;
|
|
INT oxcODT;
|
|
INT oxrCDT = 0;
|
|
INT oxrHDT = 0;
|
|
INT oycODT;
|
|
INT oyrCDT = 0;
|
|
INT oyrHDT = 0;
|
|
INT PrevGhostState = SG_NONE;
|
|
INT idResetGhostTimer = 0;
|
|
UINT wmRefreshMsg;
|
|
MYSTARTUPINFO *pStartupInfo = NULL;
|
|
RECT rcrDT;
|
|
RECT rcrMS;
|
|
BOOL fStartingAnApp;
|
|
INT PopupGhostIndex;
|
|
INT PopupRealIndex;
|
|
POINT PopupPt;
|
|
HWND PopuphwndFocus;
|
|
HMENU hMenuTopdesk;
|
|
HMENU hMenuDesktop;
|
|
HMENU hMenuWindows;
|
|
HMENU hMenuHelp;
|
|
|
|
|
|
// This structure holds the topdesk profile information - the state of MD.
|
|
|
|
WINSTATE winstate[MAX_REMEMBER];
|
|
WINSTATE ghoststate[MAX_REMEMBER];
|
|
LPTSTR pszElementNames[MAX_ICOLOR] =
|
|
{
|
|
TEXT("") , // filler for no color
|
|
NULL , // SPACECOLOR
|
|
NULL , // WINDOWFILLCOLOR
|
|
NULL , // WINDOWFRAMECOLOR
|
|
TEXT("") , // DESKFILLCOLOR
|
|
NULL , // DESKFRAMECOLOR
|
|
NULL , // GRIDCOLOR
|
|
NULL , // GHOSTFRAMECOLOR
|
|
NULL , // WINDOWTEXT
|
|
NULL , // FIXEDFRAMECOLOR
|
|
NULL // GHOSTTEXTCOLOR
|
|
};
|
|
|
|
|
|
// This array controls colors. It allows us to keep track of your brushes.
|
|
|
|
HBR orgColors[MAX_ICOLOR] = {
|
|
{ 0, 0, 1 }, // filler for no color
|
|
{ 0, RGB( 0, 0, 0 ),0 }, // SPACECOLOR
|
|
{ 0, RGB( 0, 0xff, 0xff),0 }, // WINDOWFILLCOLOR
|
|
{ 0, RGB( 0, 0, 0xff),0 }, // WINDOWFRAMECOLOR
|
|
{ 0, 0, COLOR_BACKGROUND }, // DESKFILLCOLOR
|
|
{ 0, RGB( 0, 0xff, 0 ),0 }, // DESKFRAMECOLOR
|
|
{ 0, RGB( 0xff, 0, 0 ),0 }, // GRIDCOLOR
|
|
{ 0, RGB( 0xff, 0xff, 0xff),0 }, // GHOSTFRAMECOLOR
|
|
{ 0, RGB( 0, 0, 0 ),0 }, // WINDOWTEXT
|
|
{ 0, RGB( 0xff, 0xff, 0 ),0 }, // FIXEDFRAMECOLOR
|
|
{ 0, RGB( 0xff, 0xff, 0xff),0 }, // GHOSTTEXTCOLOR
|
|
};
|
|
|
|
PRO pro = {
|
|
{ // lf
|
|
-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TEXT("Arial")
|
|
},
|
|
|
|
{ 0 }, // ahbr is set up at init time.
|
|
|
|
{ // CustColors[]
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0xff, 0xff, 0xff)
|
|
},
|
|
|
|
FALSE, // fShift;
|
|
FALSE, // fAlt;
|
|
TRUE, // fControl;
|
|
' ', // vkey;
|
|
1, // mfx;
|
|
1, // mfy;
|
|
1, // mfxAlt;
|
|
1, // mfyAlt;
|
|
0, // x;
|
|
0, // y;
|
|
0, // cx;
|
|
0, // cy;
|
|
SG_NONE, // iShowGhosts;
|
|
FALSE, // fRelative;
|
|
TRUE, // fDistOnStart;
|
|
TRUE, // fShowFrameCtrls;
|
|
FALSE, // fAutoAdj;
|
|
FALSE, // fAlwaysOnTop;
|
|
FALSE, // fHideNoFocus;
|
|
};
|
|
|
|
/**************************************/
|
|
|
|
// Calculation functions
|
|
|
|
// Conversions
|
|
|
|
INT xr2xc(
|
|
INT xr)
|
|
{
|
|
return(INT)(((LONG)(xr + oxrCDT) * (LONG)cxcDT / (LONG)cxrDT) + oxcODT);
|
|
}
|
|
|
|
|
|
|
|
INT yr2yc(
|
|
INT yr)
|
|
{
|
|
return(INT)(((LONG)(yr + oyrCDT) * (LONG)cycDT / (LONG)cyrDT) + oycODT);
|
|
}
|
|
|
|
|
|
|
|
INT xc2xr(
|
|
INT xc)
|
|
{
|
|
return(INT)(((LONG)(xc - oxcODT) * (LONG)cxrDT / (LONG)cxcDT) - oxrCDT);
|
|
}
|
|
|
|
|
|
|
|
INT yc2yr(
|
|
INT yc)
|
|
{
|
|
return(INT)(((LONG)(yc - oycODT) * (LONG)cyrDT / (LONG)cycDT) - oyrCDT);
|
|
}
|
|
|
|
|
|
|
|
VOID rRect2cRect(
|
|
PRECT prcr)
|
|
{
|
|
prcr->left = xr2xc(prcr->left);
|
|
prcr->right = xr2xc(prcr->right);
|
|
prcr->top = yr2yc(prcr->top);
|
|
prcr->bottom = yr2yc(prcr->bottom);
|
|
}
|
|
|
|
|
|
|
|
VOID cRect2rRect(
|
|
PRECT prcc)
|
|
{
|
|
prcc->left = xc2xr(prcc->left);
|
|
prcc->right = xc2xr(prcc->right);
|
|
prcc->top = yc2yr(prcc->top);
|
|
prcc->bottom = yc2yr(prcc->bottom);
|
|
}
|
|
|
|
BOOL RectInRect(
|
|
PRECT prcInside,
|
|
PRECT prcOutside)
|
|
{
|
|
return(prcInside->left >= prcOutside->left &&
|
|
prcInside->right <= prcOutside->right &&
|
|
prcInside->top >= prcOutside->top &&
|
|
prcInside->bottom <= prcOutside->bottom);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Calculates new n?VDT, c?cDT, and o?cODT
|
|
//
|
|
// This needs to be called whenever mf? or c?c change so conversions work.
|
|
//
|
|
VOID CalcConversionFactors(
|
|
BOOL fCheckShape)
|
|
{
|
|
INT cxcDTorg, cycDTorg;
|
|
INT oe = 0;
|
|
|
|
cxcDTorg = cxcDT;
|
|
cycDTorg = cycDT;
|
|
|
|
Recalc:
|
|
|
|
oe++; // causes alternating direction first checks
|
|
|
|
nxVDT = (pro.mfx << 1) + 1;
|
|
nyVDT = (pro.mfy << 1) + 1;
|
|
|
|
cxcDT = (cxc + pro.mfx) / nxVDT;
|
|
cycDT = (cyc + pro.mfy) / nyVDT;
|
|
|
|
if (fCheckShape && pro.fAutoAdj) {
|
|
if (cycDT > cxcDT * 2) {
|
|
|
|
// Too tall - fix it!
|
|
if (oe & 1) {
|
|
if (cycDTorg < cycDT) { // if its taller than it was...
|
|
if (cycDT > cycDTmin) {
|
|
pro.mfy++; // make it shorter
|
|
goto Recalc;
|
|
}
|
|
}
|
|
}
|
|
if (cxcDTorg > cxcDT) { // if its skinner than it was...
|
|
if (pro.mfx > 0) {
|
|
pro.mfx--; // make it fatter
|
|
goto Recalc;
|
|
}
|
|
}
|
|
if (!(oe & 1)) {
|
|
if (cycDTorg < cycDT) { // if its taller than it was...
|
|
if (cycDT > cycDTmin) {
|
|
pro.mfy++; // make it shorter
|
|
goto Recalc;
|
|
}
|
|
}
|
|
}
|
|
if (cycDT > cycDTmin) {
|
|
pro.mfy++; // make it shorter if we can
|
|
goto Recalc;
|
|
}
|
|
if (pro.mfx > 0) {
|
|
pro.mfx--; // make it fatter if we can
|
|
goto Recalc;
|
|
}
|
|
}
|
|
if (cxcDT > cycDT * 2) {
|
|
|
|
// Too fat - fix it!
|
|
|
|
if (oe & 1) {
|
|
if (cxcDTorg < cxcDT) { // if its fatter than it was...
|
|
if (cxcDT > cxcDTmin) {
|
|
pro.mfx++; // make it skinnier
|
|
goto Recalc;
|
|
}
|
|
}
|
|
}
|
|
if (cycDTorg > cycDT) { // if its shorter than it was...
|
|
if (pro.mfy > 0) {
|
|
pro.mfy--; // make it taller
|
|
goto Recalc;
|
|
}
|
|
}
|
|
if (!(oe & 1)) {
|
|
if (cxcDTorg < cxcDT) { // if its fatter than it was...
|
|
if (cxcDT > cxcDTmin) {
|
|
pro.mfx++; // make it skinnier
|
|
goto Recalc;
|
|
}
|
|
}
|
|
}
|
|
if (cxcDT > cxcDTmin) {
|
|
pro.mfx++; // make it skinnier
|
|
goto Recalc;
|
|
}
|
|
if (pro.mfy > 0) {
|
|
pro.mfy--; // make it taller
|
|
goto Recalc;
|
|
}
|
|
}
|
|
}
|
|
|
|
oxcODT = cxcDT * pro.mfx;
|
|
oycODT = cycDT * pro.mfy;
|
|
}
|
|
|
|
|
|
LPTSTR GetResString(
|
|
DWORD id)
|
|
{
|
|
LoadString(hInst, id, szResString, sizeof(szResString));
|
|
return(szResString);
|
|
}
|
|
|
|
VOID DrawIndentRect(
|
|
HDC hdc,
|
|
PRECT prc)
|
|
{
|
|
HANDLE hPenSave;
|
|
|
|
SetROP2(hdc, R2_COPYPEN);
|
|
hPenSave = SelectObject(hdc, GetStockObject(BLACK_PEN));
|
|
MMoveTo(hdc, prc->left, prc->bottom - 1);
|
|
LineTo(hdc, prc->left, prc->top);
|
|
LineTo(hdc, prc->right - 1, prc->top);
|
|
SelectObject(hdc, GetStockObject(WHITE_PEN));
|
|
MMoveTo(hdc, prc->right, prc->top + 1);
|
|
LineTo(hdc, prc->right, prc->bottom);
|
|
LineTo(hdc, prc->left + 1, prc->bottom);
|
|
SelectObject(hdc, hPenSave);
|
|
}
|
|
|
|
|
|
VOID DrawExdentRect(
|
|
HDC hdc,
|
|
PRECT prc)
|
|
{
|
|
HANDLE hPenSave;
|
|
|
|
SetROP2(hdc, R2_COPYPEN);
|
|
hPenSave = SelectObject(hdc, GetStockObject(WHITE_PEN));
|
|
MMoveTo(hdc, prc->left, prc->bottom - 1);
|
|
LineTo(hdc, prc->left, prc->top);
|
|
LineTo(hdc, prc->right - 1, prc->top);
|
|
SelectObject(hdc, GetStockObject(BLACK_PEN));
|
|
MMoveTo(hdc, prc->right, prc->top + 1);
|
|
LineTo(hdc, prc->right, prc->bottom);
|
|
LineTo(hdc, prc->left + 1, prc->bottom);
|
|
SelectObject(hdc, hPenSave);
|
|
}
|
|
|
|
|
|
|
|
VOID Working(
|
|
RECT *prc)
|
|
{
|
|
HDC hdc;
|
|
HFONT hfSave;
|
|
RECT rcClient;
|
|
|
|
hdc = GetDC(hwndTopdesk);
|
|
hfSave = SelectObject(hdc, hMyFont);
|
|
GetClientRect(hwndTopdesk, &rcClient);
|
|
*prc = rcClient;
|
|
DrawText(hdc, pszWorking, -1, prc, DT_CALCRECT);
|
|
OffsetRect(prc, (rcClient.right - prc->right) / 2,
|
|
(rcClient.bottom - prc->bottom) / 2);
|
|
InflateRect(prc, 4, 4);
|
|
FillRect(hdc, prc, GetStockObject(GRAY_BRUSH));
|
|
DrawExdentRect(hdc, prc);
|
|
InflateRect(prc, -3, -3);
|
|
DrawIndentRect(hdc, prc);
|
|
InflateRect(prc, -1, -1);
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
DrawText(hdc, pszWorking, -1, prc, 0);
|
|
InflateRect(prc, 4, 4);
|
|
SelectObject(hdc, hfSave);
|
|
ReleaseDC(hwndTopdesk, hdc);
|
|
InflateRect(prc, 1, 1);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// File IO - make that registry IO!
|
|
//
|
|
|
|
|
|
BOOL MyQueryProfileSize(
|
|
LPTSTR szFname,
|
|
INT *pSize)
|
|
{
|
|
DWORD type;
|
|
|
|
*pSize = 0;
|
|
if (hKeyTopDesk == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(RegQueryValueEx(hKeyTopDesk, szFname, 0, &type, NULL, (LPDWORD)pSize)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
BOOL MyQueryProfileData(
|
|
LPTSTR szFname,
|
|
VOID *lpBuf,
|
|
INT Size)
|
|
{
|
|
DWORD type = REG_BINARY;
|
|
|
|
if (hKeyTopDesk == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(RegQueryValueEx(hKeyTopDesk, szFname, NULL, &type, lpBuf, (LPDWORD)&Size)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
UINT MyWriteProfileData(
|
|
LPTSTR szFname,
|
|
VOID *lpBuf,
|
|
UINT cb)
|
|
{
|
|
if (hKeyTopDesk == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
return(RegSetValueEx(hKeyTopDesk, szFname, 0, REG_BINARY, lpBuf, (DWORD)cb)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
MYSTARTUPINFO *CreateStartupInfo(
|
|
LPTSTR pszTitle,
|
|
LPTSTR pszStartup,
|
|
LPTSTR pszWorkDir,
|
|
BOOL fSetTitle)
|
|
{
|
|
MYSTARTUPINFO *psi;
|
|
|
|
psi = (MYSTARTUPINFO *)LocalAlloc(LPTR, sizeof(MYSTARTUPINFO));
|
|
|
|
psi->pszTitle = (LPTSTR)LocalAlloc(LPTR, (_tcslen(pszTitle) + 1) * sizeof(TCHAR));
|
|
_tcscpy(psi->pszTitle, pszTitle);
|
|
|
|
psi->pszStartup = (LPTSTR)LocalAlloc(LPTR, (_tcslen(pszStartup) + 1) * sizeof(TCHAR));
|
|
_tcscpy(psi->pszStartup, pszStartup);
|
|
|
|
psi->pszWorkDir = (LPTSTR)LocalAlloc(LPTR, (_tcslen(pszWorkDir) + 1) * sizeof(TCHAR));
|
|
_tcscpy(psi->pszWorkDir, pszWorkDir);
|
|
|
|
psi->fSetTitle = fSetTitle;
|
|
|
|
psi->next = pStartupInfo;
|
|
pStartupInfo = psi;
|
|
return(psi);
|
|
}
|
|
|
|
|
|
|
|
VOID LoadGhostState()
|
|
{
|
|
DWORD cbData, dwType;
|
|
LPTSTR pszBuf, psz, pszT;
|
|
|
|
if (RegQueryValueEx(hKeyTopDesk, pszData, NULL, &dwType, NULL, &cbData) != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
if (dwType != REG_MULTI_SZ) {
|
|
RegDeleteValue(hKeyTopDesk, pszData);
|
|
return;
|
|
}
|
|
pszBuf = LocalAlloc(LPTR, cbData);
|
|
if (pszBuf == NULL) {
|
|
return;
|
|
}
|
|
if (RegQueryValueEx(hKeyTopDesk, pszData, NULL, &dwType,
|
|
(LPBYTE)pszBuf, &cbData) != ERROR_SUCCESS) {
|
|
LocalFree(pszBuf);
|
|
return;
|
|
}
|
|
psz = pszBuf;
|
|
while (*psz != TEXT('\0')) {
|
|
if (_stscanf(psz, TEXT("(%08d,%08d,%08d,%08d),%08x"),
|
|
&ghoststate[cGhosts].rc.left,
|
|
&ghoststate[cGhosts].rc.right,
|
|
&ghoststate[cGhosts].rc.top,
|
|
&ghoststate[cGhosts].rc.bottom,
|
|
&ghoststate[cGhosts].style) == 5) {
|
|
pszT = _tcschr(psz, TEXT('['));
|
|
if (pszT != NULL && *pszT == TEXT('[')) {
|
|
_tcscpy(ghoststate[cGhosts].szTitle, pszT + 1);
|
|
pszT = _tcsrchr(ghoststate[cGhosts].szTitle, TEXT(']'));
|
|
if (pszT != NULL) {
|
|
*pszT = TEXT('\0');
|
|
}
|
|
ghoststate[cGhosts].hwnd = 0;
|
|
cGhosts++;
|
|
psz += _tcslen(psz) + 1;
|
|
}
|
|
}
|
|
}
|
|
LocalFree(pszBuf);
|
|
}
|
|
|
|
|
|
|
|
VOID SaveGhostState()
|
|
{
|
|
TCHAR psz[200];
|
|
LPTSTR pszBuf;
|
|
DWORD cchTotal, cchPrev;
|
|
int i;
|
|
|
|
if (cGhosts == 0) {
|
|
RegDeleteValue(hKeyTopDesk, pszData);
|
|
return;
|
|
}
|
|
|
|
MoveGhosts(oxrCDT - oxrHDT, oyrCDT - oyrHDT);
|
|
|
|
cchTotal = 0;
|
|
for (i = 0; i < cGhosts; i++) {
|
|
cchPrev = cchTotal;
|
|
wsprintf(psz, TEXT("(%08d,%08d,%08d,%08d),%08x,[%s]"),
|
|
ghoststate[i].rc.left,
|
|
ghoststate[i].rc.right,
|
|
ghoststate[i].rc.top,
|
|
ghoststate[i].rc.bottom,
|
|
ghoststate[i].style,
|
|
ghoststate[i].szTitle);
|
|
cchTotal += _tcslen(psz) + 1;
|
|
if (i == 0) {
|
|
pszBuf = LocalAlloc(LPTR, (cchTotal + 1) * sizeof(TCHAR));
|
|
} else {
|
|
pszBuf = LocalReAlloc(pszBuf, (cchTotal + 1) * sizeof(TCHAR),
|
|
LMEM_MOVEABLE);
|
|
}
|
|
if (pszBuf == NULL) {
|
|
return; // FAILED
|
|
}
|
|
_tcscpy(&pszBuf[cchPrev], psz);
|
|
}
|
|
pszBuf[cchTotal] = TEXT('\0');
|
|
RegSetValueEx(hKeyTopDesk, pszData, 0, REG_MULTI_SZ,
|
|
(LPBYTE)pszBuf, (cchTotal + 1) * sizeof(TCHAR));
|
|
LocalFree(pszBuf);
|
|
|
|
MoveGhosts(oxrHDT - oxrCDT, oyrHDT - oyrCDT);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Returns FALSE if the profile portion was not read in ok.
|
|
* GhostState and StartupInfo input do not effect the return value.
|
|
* This is so topdesk can use the desktop size to determine the default
|
|
* placement of topdesk.
|
|
*/
|
|
BOOL GetProfile()
|
|
{
|
|
INT c;
|
|
BOOL fRet = FALSE;
|
|
|
|
//
|
|
// startup info
|
|
//
|
|
MyQueryProfileSize(pszStartupInfo, &c);
|
|
if (c) {
|
|
LPTSTR pBuf, pszT, pszTitle, pszStartup, pszWorkDir;
|
|
BOOL fSetTitle;
|
|
|
|
pBuf = (LPTSTR)LocalAlloc(LPTR, c);
|
|
if (pBuf != NULL) {
|
|
MyQueryProfileData(pszStartupInfo, pBuf, c);
|
|
pszTitle = pBuf;
|
|
while (*pszTitle) {
|
|
fSetTitle = FALSE;
|
|
if (pszTitle[0] == TEXT('*')) {
|
|
fSetTitle = TRUE;
|
|
pszTitle++;
|
|
} else if (pszTitle[0] == TEXT(' ')) {
|
|
pszTitle++;
|
|
}
|
|
pszStartup = _tcschr(pszTitle, TEXT('='));
|
|
if (pszStartup == NULL) {
|
|
break;
|
|
}
|
|
*pszStartup++ = TEXT('\0');
|
|
pszWorkDir = _tcschr(pszStartup, TEXT('@'));
|
|
if (pszWorkDir == NULL) {
|
|
break;
|
|
}
|
|
*pszWorkDir++ = TEXT('\0');
|
|
pszT = pszWorkDir;
|
|
while (*pszT++) {
|
|
;
|
|
}
|
|
|
|
CreateStartupInfo(pszTitle, pszStartup, pszWorkDir, fSetTitle);
|
|
pszTitle = pszT;
|
|
}
|
|
LocalFree((HLOCAL)pBuf);
|
|
}
|
|
}
|
|
|
|
//
|
|
// profile data
|
|
//
|
|
MyQueryProfileSize(pszProfile, &c);
|
|
if (c == sizeof(pro)) {
|
|
MyQueryProfileData(pszProfile, (LPTSTR)&pro, sizeof(pro));
|
|
fRet = TRUE;
|
|
}
|
|
|
|
LoadGhostState();
|
|
return(fRet);
|
|
}
|
|
|
|
|
|
VOID SaveProfile()
|
|
{
|
|
RECT rc;
|
|
MYSTARTUPINFO *psi;
|
|
LPTSTR pszBuf, psz;
|
|
DWORD cb = 0;
|
|
|
|
if (hKeyTopDesk == NULL) {
|
|
return;
|
|
}
|
|
if (IsIconic(hwndTopdesk)) {
|
|
ShowWindow(hwndTopdesk, SW_RESTORE);
|
|
}
|
|
GetWindowRect(hwndTopdesk, &rc); // screen coords
|
|
pro.x = (INT)rc.left;
|
|
pro.y = (INT)rc.top;
|
|
pro.cx = (INT)rc.right - (INT)rc.left;
|
|
pro.cy = (INT)rc.bottom - (INT)rc.top;
|
|
MyWriteProfileData(pszProfile, (LPTSTR)&pro, sizeof(pro));
|
|
|
|
psz = pszBuf = LocalAlloc(LPTR, 4 * 1024 * sizeof(TCHAR));
|
|
if (pszBuf != NULL) {
|
|
*pszBuf = TEXT('\0'); // zero terminate
|
|
psi = pStartupInfo;
|
|
while (psi != NULL) {
|
|
_tcscat(pszBuf, psi->fSetTitle ? TEXT("*") : TEXT(" "));
|
|
_tcscat(pszBuf, psi->pszTitle);
|
|
_tcscat(pszBuf, TEXT("="));
|
|
_tcscat(pszBuf, psi->pszStartup);
|
|
_tcscat(pszBuf, TEXT("@"));
|
|
_tcscat(pszBuf, psi->pszWorkDir);
|
|
cb += (_tcslen(pszBuf) + 1) * sizeof(TCHAR);
|
|
pszBuf = _tcschr(pszBuf, TEXT('\0'));
|
|
pszBuf++;
|
|
*pszBuf = TEXT('\0');
|
|
psi = psi->next;
|
|
}
|
|
}
|
|
cb += sizeof(TCHAR);
|
|
RegSetValueEx(hKeyTopDesk, pszStartupInfo, 0, REG_MULTI_SZ, (BYTE *)psz, cb);
|
|
LocalFree(psz);
|
|
}
|
|
|
|
|
|
VOID FreeStartupInfo()
|
|
{
|
|
MYSTARTUPINFO *psi;
|
|
|
|
psi = pStartupInfo;
|
|
while (psi != NULL) {
|
|
LocalFree((HLOCAL)psi->pszTitle);
|
|
LocalFree((HLOCAL)psi->pszStartup);
|
|
LocalFree((HLOCAL)psi->pszWorkDir);
|
|
psi = pStartupInfo->next;
|
|
LocalFree((HLOCAL)pStartupInfo);
|
|
pStartupInfo = psi;
|
|
}
|
|
}
|
|
|
|
VOID CreateBrushes()
|
|
{
|
|
INT i;
|
|
|
|
for (i = 1; i < MAX_ICOLOR; i++) {
|
|
if (pro.ahbr[i].syscolor) {
|
|
pro.ahbr[i].color = GetSysColor((INT)(pro.ahbr[i].syscolor));
|
|
}
|
|
pro.ahbr[i].hbr = CreateSolidBrush(pro.ahbr[i].color);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID DeleteBrushes()
|
|
{
|
|
INT i;
|
|
|
|
for (i = 1; i < MAX_ICOLOR; i++) {
|
|
DeleteObject(pro.ahbr[i].hbr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Window and ghost manipulation
|
|
//
|
|
|
|
|
|
|
|
|
|
VOID MoveGhosts(
|
|
INT dx,
|
|
INT dy)
|
|
{
|
|
INT i;
|
|
|
|
for (i = 0; i < cGhosts; i++) {
|
|
if (!(ghoststate[i].style & WISF_FIXED)) {
|
|
OffsetRect(&ghoststate[i].rc, dx, dy);
|
|
}
|
|
}
|
|
OffsetRect(&rcrMS, dx, dy);
|
|
}
|
|
|
|
|
|
|
|
INT FindIndexFromHwnd(
|
|
HWND hwnd)
|
|
{
|
|
INT iReal;
|
|
|
|
for (iReal = 0; iReal < cWindows; iReal++) {
|
|
if (winstate[iReal].hwnd == hwnd) {
|
|
return(iReal);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID MyMoveWindow(
|
|
HWND hwnd,
|
|
INT iLeft,
|
|
INT iTop,
|
|
INT cx,
|
|
INT cy)
|
|
{
|
|
int iReal;
|
|
RECT rc;
|
|
|
|
if (!(GetWindowLong(hwnd, GWL_STYLE) & WS_MINIMIZE)) {
|
|
Working(&rc);
|
|
for (iReal = 0; iReal < cWindows; iReal++) {
|
|
if (winstate[iReal].hwnd == hwnd) {
|
|
SetRect(&winstate[iReal].rc, iLeft, iTop, iLeft + cx, iTop + cy);
|
|
MoveWindow(hwnd, iLeft, iTop, cx, cy, TRUE);
|
|
break;
|
|
}
|
|
}
|
|
InvalidateRect(hwndTopdesk, &rc, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID MoveChildren(
|
|
INT cx,
|
|
INT cy)
|
|
{
|
|
HDWP hdwp;
|
|
INT i;
|
|
RECT rc;
|
|
|
|
if (cx == 0 && cy == 0) {
|
|
return;
|
|
}
|
|
hdwp = BeginDeferWindowPos(MAX_CHILDREN);
|
|
if (hdwp == NULL) {
|
|
return;
|
|
}
|
|
Working(&rc);
|
|
for (i = 0; i < cWindows; i++) {
|
|
if (!(winstate[i].style & (WISF_FIXED | WS_MINIMIZE)) &&
|
|
winstate[i].hwnd != hwndTopdesk &&
|
|
IsWindow(winstate[i].hwnd)) {
|
|
OffsetRect(&winstate[i].rc, cx, cy);
|
|
hdwp = DeferWindowPos(hdwp, winstate[i].hwnd, (HWND)0,
|
|
winstate[i].rc.left, winstate[i].rc.top, 0, 0,
|
|
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
|
|
InvalidateRect(hwndTopdesk, &rc, FALSE);
|
|
}
|
|
}
|
|
EndDeferWindowPos(hdwp);
|
|
|
|
MoveGhosts(cx, cy);
|
|
if (pro.fRelative) {
|
|
oxrHDT += cx; // relative keeps CDT in center
|
|
oyrHDT += cy;
|
|
} else {
|
|
oxrCDT -= cx; // absolute keeps HDT in center
|
|
oyrCDT -= cy;
|
|
}
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
}
|
|
|
|
|
|
VOID GatherWindow(
|
|
INT iReal)
|
|
{
|
|
RECT rc;
|
|
|
|
if (winstate[iReal].hwnd != hwndTopdesk) {
|
|
if (RectInRect(&winstate[iReal].rc, &rcrDT)) {
|
|
return;
|
|
}
|
|
/*
|
|
* bring top-center of window onto desktop.
|
|
*/
|
|
while (((winstate[iReal].rc.left +
|
|
winstate[iReal].rc.right) / 2) > cxrDT) {
|
|
winstate[iReal].rc.left -= cxrDT;
|
|
winstate[iReal].rc.right -= cxrDT;
|
|
}
|
|
while (((winstate[iReal].rc.left +
|
|
winstate[iReal].rc.right) / 2) < 0) {
|
|
winstate[iReal].rc.left += cxrDT;
|
|
winstate[iReal].rc.right += cxrDT;
|
|
}
|
|
while (winstate[iReal].rc.top + 8 > cyrDT) {
|
|
winstate[iReal].rc.top -= cyrDT;
|
|
winstate[iReal].rc.bottom -= cyrDT;
|
|
}
|
|
while (winstate[iReal].rc.top + 8 < 0) {
|
|
winstate[iReal].rc.top += cyrDT;
|
|
winstate[iReal].rc.bottom += cyrDT;
|
|
}
|
|
Working(&rc);
|
|
MoveWindow(winstate[iReal].hwnd,
|
|
winstate[iReal].rc.left, winstate[iReal].rc.top,
|
|
winstate[iReal].rc.right - winstate[iReal].rc.left,
|
|
winstate[iReal].rc.bottom - winstate[iReal].rc.top,
|
|
TRUE);
|
|
InvalidateRect(hwndTopdesk, &rc, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID GatherWindows()
|
|
{
|
|
INT i;
|
|
|
|
for (i = 0; i < cWindows; i++) {
|
|
GatherWindow(i);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID DeleteGhostWindow(
|
|
INT iGhost)
|
|
{
|
|
INT j;
|
|
|
|
if (pro.iShowGhosts) {
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
}
|
|
if (ghoststate[iGhost].style & WISF_LINKED) {
|
|
for (j = 0; j < cWindows; j++) {
|
|
if (ghoststate[iGhost].hwnd == winstate[j].hwnd) {
|
|
winstate[j].style &= ~WISF_LINKED;
|
|
}
|
|
}
|
|
}
|
|
|
|
cGhosts--;
|
|
|
|
if (iGhost < cGhosts) {
|
|
memmove(&ghoststate[iGhost], &ghoststate[iGhost + 1],
|
|
sizeof(WINSTATE) * (cGhosts - iGhost));
|
|
}
|
|
SaveGhostState();
|
|
}
|
|
|
|
|
|
|
|
VOID ModifyTitle(
|
|
LPTSTR pstr)
|
|
{
|
|
LPTSTR pch;
|
|
INT cch;
|
|
|
|
//
|
|
// first strip off anything with and including TEXT(" - "), TEXT("["), or TEXT("(")
|
|
//
|
|
pch = _tcsstr(pstr, TEXT(" - "));
|
|
if (pch != NULL) {
|
|
*pch = TEXT('\0');
|
|
}
|
|
pch = _tcschr(pstr, TEXT('['));
|
|
if (pch != NULL) {
|
|
*pch = TEXT('\0');
|
|
}
|
|
pch = _tcschr(pstr, TEXT('('));
|
|
if (pch != NULL) {
|
|
*pch = TEXT('\0');
|
|
}
|
|
//
|
|
// remove trailing spaces
|
|
//
|
|
pch = pstr + _tcslen(pstr);
|
|
while (*(--pch) == TEXT(' ') && pch >= pstr) {
|
|
*pch = TEXT('\0');
|
|
}
|
|
|
|
//
|
|
// strip out any file extension or path name
|
|
//
|
|
cch = _tcslen(pstr);
|
|
pch = pstr + cch;
|
|
|
|
while (cch-- > 0) {
|
|
switch(*pch) {
|
|
case TEXT('.'):
|
|
/* get rid of extension */
|
|
*pch = TEXT('\0');
|
|
break;
|
|
|
|
case TEXT('\\'):
|
|
case TEXT('/':)
|
|
case TEXT(':':)
|
|
/* found end of path or drive name, move root portion
|
|
to start of scScratch */
|
|
_tcscpy(pstr,pch + 1);
|
|
/* and get out of here */
|
|
cch = 0;
|
|
}
|
|
pch--;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID GetModifiedWindowTitle(
|
|
HWND hwnd,
|
|
LPTSTR pstr) // ASSUME size == MAX_SZTITLE!
|
|
{
|
|
if (!GetWindowText(hwnd, pstr, MAX_SZTITLE)) {
|
|
*pstr = TEXT('\0');
|
|
return;
|
|
}
|
|
pstr[MAX_SZTITLE - 1] = TEXT('\0');
|
|
|
|
ModifyTitle(pstr);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
DWORD UpdateState(
|
|
WINSTATE *pws,
|
|
HWND hwnd)
|
|
{
|
|
TCHAR szTitle[MAX_SZTITLE];
|
|
RECT rc;
|
|
DWORD fChanged = 0;
|
|
DWORD style;
|
|
|
|
if (!IsWindow(hwnd)) {
|
|
return(FALSE);
|
|
}
|
|
//
|
|
// update database info - preserving any custom style flags.
|
|
//
|
|
if (pws->hwnd != hwnd) {
|
|
fChanged |= 1;
|
|
pws->hwnd = hwnd;
|
|
}
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
if (!EqualRect(&rc, &pws->rc)) {
|
|
fChanged |= 1;
|
|
pws->rc = rc;
|
|
}
|
|
|
|
style = (GetWindowLong(hwnd, GWL_STYLE) & WS_TRACKEDSTYLES) |
|
|
(pws->style & WISF_CUSTOMSTYLES);
|
|
if (style != pws->style) {
|
|
fChanged |= 1;
|
|
pws->style = style;
|
|
}
|
|
|
|
GetModifiedWindowTitle(hwnd, szTitle);
|
|
szTitle[MAX_SZTITLE - 1] = TEXT('\0');
|
|
if (_tcscmp(pws->szTitle, szTitle)) {
|
|
fChanged |= 2;
|
|
_tcscpy(pws->szTitle, szTitle);
|
|
}
|
|
|
|
return(fChanged);
|
|
}
|
|
|
|
|
|
INT FindLinkableGhost(
|
|
INT iReal)
|
|
{
|
|
INT iGhost;
|
|
|
|
if (!IsWindow(winstate[iReal].hwnd)) {
|
|
return(-1);
|
|
}
|
|
|
|
//
|
|
// Try iStartGhost first - this way multiple ghosts with the same
|
|
// name don't fool us.
|
|
//
|
|
if (iStartGhost != -1 && ghoststate[iStartGhost].hwnd == 0) {
|
|
DPRINTF((hfDbgOut, "IsLinkableStartGhost(%ls, %ls) ",
|
|
ghoststate[iStartGhost].szTitle, winstate[iReal].szTitle));
|
|
if (!_tcsicmp(ghoststate[iStartGhost].szTitle, winstate[iReal].szTitle)) {
|
|
DPRINTF((hfDbgOut, "matched.\n"));
|
|
iGhost = iStartGhost;
|
|
iStartGhost = -1;
|
|
return(iGhost);
|
|
} else {
|
|
DPRINTF((hfDbgOut, "did not match.\n"));
|
|
}
|
|
}
|
|
|
|
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
|
|
if (ghoststate[iGhost].hwnd == 0) {
|
|
DPRINTF((hfDbgOut, "IsLinkableGhost(%ls, %ls) ",
|
|
ghoststate[iGhost].szTitle, winstate[iReal].szTitle));
|
|
if (!_tcsicmp(ghoststate[iGhost].szTitle, winstate[iReal].szTitle)) {
|
|
DPRINTF((hfDbgOut, "matched.\n"));
|
|
return(iGhost);
|
|
} else {
|
|
DPRINTF((hfDbgOut, "did not match.\n"));
|
|
}
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
INT FindLinkedGhost(
|
|
INT iReal)
|
|
{
|
|
INT iGhost;
|
|
|
|
if (!IsWindow(winstate[iReal].hwnd)) {
|
|
return(-1);
|
|
}
|
|
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
|
|
if (ghoststate[iGhost].hwnd == winstate[iReal].hwnd) {
|
|
return(iGhost);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
VOID Unlink(
|
|
INT iReal,
|
|
INT iGhost)
|
|
{
|
|
winstate[iReal].style &= ~WISF_LINKED;
|
|
ghoststate[iGhost].style &= ~WISF_LINKED;
|
|
ghoststate[iGhost].hwnd = 0;
|
|
}
|
|
|
|
|
|
|
|
INT FindLinkedReal(
|
|
INT iGhost)
|
|
{
|
|
INT iReal;
|
|
|
|
for (iReal = 0; iReal < cWindows; iReal++) {
|
|
if (ghoststate[iGhost].hwnd == winstate[iReal].hwnd) {
|
|
if (IsWindow(winstate[iReal].hwnd)) {
|
|
return(iReal);
|
|
} else {
|
|
Unlink(iReal, iGhost);
|
|
return(-1);
|
|
}
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
|
|
VOID LinkWindows(
|
|
INT iReal,
|
|
INT iGhost,
|
|
BOOL fSnapGhost)
|
|
{
|
|
winstate[iReal].style |= WISF_LINKED;
|
|
ghoststate[iGhost].style |= WISF_LINKED;
|
|
ghoststate[iGhost].hwnd = winstate[iReal].hwnd;
|
|
_tcscpy(ghoststate[iGhost].szTitle, winstate[iReal].szTitle);
|
|
if (fSnapGhost) {
|
|
ghoststate[iGhost] = winstate[iReal];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
INT DistributeWindow(
|
|
INT iReal,
|
|
INT iGhost)
|
|
{
|
|
RECT rc;
|
|
|
|
if (iReal == -1) {
|
|
iReal = FindLinkedReal(iGhost);
|
|
}
|
|
if (iGhost == -1) {
|
|
iGhost = FindLinkedGhost(iReal);
|
|
}
|
|
if (iGhost == -1) {
|
|
return(iReal);
|
|
}
|
|
//
|
|
// If there is a difference between the linked ghost state and
|
|
// the window state, make them match.
|
|
//
|
|
if ((winstate[iReal].style ^ ghoststate[iGhost].style) &
|
|
(WS_MINIMIZE | WS_MAXIMIZE)) {
|
|
|
|
if (winstate[iReal].style & WS_MINIMIZE) {
|
|
// this is so DOS windows do the right thing
|
|
SendMessage(winstate[iReal].hwnd, WM_LBUTTONDBLCLK, 0, 0);
|
|
}
|
|
|
|
if (ghoststate[iGhost].style & WS_MINIMIZE) {
|
|
SendMessage(winstate[iReal].hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
|
|
} else if (ghoststate[iGhost].style & WS_MAXIMIZE) {
|
|
SendMessage(winstate[iReal].hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
|
|
} else {
|
|
SendMessage(winstate[iReal].hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
|
|
}
|
|
}
|
|
winstate[iReal].style = ghoststate[iGhost].style;
|
|
|
|
//
|
|
// move the real window to where the ghost is.
|
|
//
|
|
Working(&rc);
|
|
MyMoveWindow(winstate[iReal].hwnd, ghoststate[iGhost].rc.left,
|
|
ghoststate[iGhost].rc.top,
|
|
ghoststate[iGhost].rc.right - ghoststate[iGhost].rc.left,
|
|
ghoststate[iGhost].rc.bottom - ghoststate[iGhost].rc.top);
|
|
InvalidateRect(hwndTopdesk, &rc, FALSE);
|
|
return(iReal);
|
|
}
|
|
|
|
|
|
INT FindRealLink(
|
|
INT iGhost)
|
|
{
|
|
INT iReal;
|
|
|
|
if (!ghoststate[iGhost].hwnd) {
|
|
return(-1);
|
|
}
|
|
for (iReal = 0; iReal < cWindows; iReal++) {
|
|
if (winstate[iReal].hwnd == ghoststate[iGhost].hwnd) {
|
|
return(iReal);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
VOID GetBestGuessRect(
|
|
PRECT prcOut,
|
|
WINSTATE *pws)
|
|
{
|
|
GetWindowRect(pws->hwnd, &pws->rc);
|
|
*prcOut = pws->rc;
|
|
}
|
|
|
|
|
|
/*
|
|
* The critical point of a rectangle is that point which TopDesk uses
|
|
* to determine what desktop the window is on.
|
|
*/
|
|
VOID GetCriticalPoint(
|
|
PRECT prc,
|
|
int *px,
|
|
int *py)
|
|
{
|
|
*px = (prc->left + prc->right) / 2;
|
|
if (prc->bottom - prc->top > cyrDT) {
|
|
*py = (prc->top + prc->bottom) / 2;
|
|
} else {
|
|
*py = prc->top + GetSystemMetrics(SM_CYCAPTION) / 2;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOL IsCriticalPointOnDesktop(
|
|
PRECT prc)
|
|
{
|
|
POINT pt;
|
|
|
|
GetCriticalPoint(prc, &pt.x, &pt.y);
|
|
return(PtInRect(&rcrDT, pt));
|
|
}
|
|
|
|
|
|
BOOL APIENTRY RefreshEnumProc(
|
|
HWND hwnd,
|
|
LONG l)
|
|
{
|
|
INT j;
|
|
BOOL fNew = FALSE;
|
|
RECT rc;
|
|
WINSTATE winstateT;
|
|
DWORD StateChanges;
|
|
TCHAR szClass[30];
|
|
|
|
l;
|
|
|
|
if (iRefresh >= MAX_REMEMBER - 1) {
|
|
iRefresh++;
|
|
return(FALSE); // overflow
|
|
}
|
|
|
|
if (!IsWindow(hwnd)) {
|
|
return(TRUE);
|
|
}
|
|
|
|
if (!IsWindowVisible(hwnd)) {
|
|
return(TRUE); // don't remember invisible windows
|
|
}
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
if (IsRectEmpty(&rc)) {
|
|
return(TRUE); // don't remember 0 sized windows
|
|
}
|
|
|
|
if (GetWindowTextLength(hwnd) == 0) { // skip empty title windows too.
|
|
return(TRUE);
|
|
}
|
|
/*
|
|
* Skip the vslick owner window - its real trouble.
|
|
*/
|
|
GetClassName(hwnd, szClass, sizeof(szClass) / sizeof(szClass[0]));
|
|
if (!_tcscmp(szClass, TEXT("Visual SlickEdit"))) {
|
|
return(TRUE);
|
|
}
|
|
|
|
/*
|
|
* If we are runing with the cairo shell, don't show the full screen
|
|
* sized program manager window. (which draws the icons for the new
|
|
* shell and handles DDE.) We will still accept progman windows that
|
|
* aren't the size of the desktop because the person could be runing
|
|
* progman at the same time. (like me)
|
|
*/
|
|
if (fCairoShell) {
|
|
static TCHAR szProgman[] = TEXT("Program Manager");
|
|
TCHAR szBuf[25];
|
|
RECT rc;
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
if (GetWindowText(hwnd, szBuf, sizeof(szBuf) / sizeof(TCHAR)) &&
|
|
!_tcscmp(szBuf, szProgman) &&
|
|
EqualRect(&rc, &rcrDT)) {
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
if ((iRefresh >= cWindows || winstate[iRefresh].hwnd != hwnd)) {
|
|
//
|
|
// Something has changed or been added.
|
|
//
|
|
fInvalidated = TRUE;
|
|
fNew = TRUE;
|
|
for (j = iRefresh + 1; j < cWindows; j++) {
|
|
if (j < MAX_REMEMBER) {
|
|
//
|
|
// see if it was a Z-order change
|
|
//
|
|
if (winstate[j].hwnd == hwnd) {
|
|
//
|
|
// yes it was... its not new, just swap.
|
|
//
|
|
fNew = FALSE;
|
|
winstateT = winstate[j];
|
|
winstate[j] = winstate[iRefresh];
|
|
winstate[iRefresh] = winstateT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (fNew) {
|
|
if (iRefresh < (cWindows - 1)) {
|
|
/*
|
|
* new window - make room
|
|
*/
|
|
memmove(&winstate[iRefresh + 1], &winstate[iRefresh],
|
|
sizeof(WINSTATE) * (cWindows - iRefresh));
|
|
}
|
|
if (cWindows < MAX_REMEMBER) {
|
|
cWindows++;
|
|
}
|
|
|
|
winstate[iRefresh].style = 0; // clear custom flags.
|
|
|
|
if (pszSetTitle != NULL) {
|
|
SetWindowText(hwnd, pszSetTitle);
|
|
pszSetTitle = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
StateChanges = UpdateState(&winstate[iRefresh], hwnd);
|
|
if (StateChanges) {
|
|
/*
|
|
* If there is no ghost associated with this window then set
|
|
* fNew so we can link it to a ghost if its name changed
|
|
* during startup. (ex. WinHelp alters its name on startup
|
|
* and will not link to a ghost under certain timing conditions.
|
|
*/
|
|
if ((StateChanges & 2) && FindLinkedGhost(iRefresh) == -1) {
|
|
fNew = TRUE;
|
|
}
|
|
fInvalidated = TRUE;
|
|
}
|
|
if (fNew) {
|
|
|
|
/*
|
|
* 2 hacks:
|
|
* 1) Make topdesk's help window automatically locked.
|
|
* 2) vslick uses an off-screen owner window that will move
|
|
* with its ownee. If we move the ownee, the owner
|
|
* will move and then when we move the owner, the ownee
|
|
* will move again, so we always lock the ownee.
|
|
*/
|
|
if (!_tcscmp(winstate[iRefresh].szTitle, pszTopdeskHelpTitle)
|
|
// || !_tcscmp(TEXT("vs_mdiframe"), szClass)
|
|
)
|
|
{
|
|
|
|
winstate[iRefresh].style |= WISF_FIXED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// See if we can associate an unlinked ghost window with this.
|
|
// If so, make the real window adapt to match the ghost. (auto place)
|
|
// if pro.fDistOnStart is set.
|
|
//
|
|
if (fNew && hwnd != hwndTopdesk) {
|
|
j = FindLinkableGhost(iRefresh);
|
|
if (j > -1) {
|
|
LinkWindows(iRefresh, j, FALSE);
|
|
if (pro.fDistOnStart) {
|
|
if (ihwndJump == -1) {
|
|
ihwndJump = DistributeWindow(iRefresh, j);
|
|
} else if (ihwndJump == -2) {
|
|
//
|
|
// this is so at startup the windows get distributed but
|
|
// the desktop doesn't jump around.
|
|
//
|
|
DistributeWindow(iRefresh, j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See if the top window is on the screen. If not, we need to jump.
|
|
* This is a hack so that CMD windows, which cannot be hooked, will
|
|
* be jumped to when focus changes.
|
|
*/
|
|
if (iRefresh == 0 && ihwndJump == -1) {
|
|
int i;
|
|
HWND hwndForeground = GetForegroundWindow();
|
|
|
|
/*
|
|
* because of WM_TOPMOST, the top window may not have the focus
|
|
* so make sure we have the right one.
|
|
*/
|
|
if (hwndForeground) {
|
|
for (i = 0; i < MAX_REMEMBER; i++) {
|
|
if (winstate[i].hwnd && IsChild(winstate[i].hwnd, hwndForeground)) {
|
|
GetBestGuessRect(&rc, &winstate[i]);
|
|
if (!IsCriticalPointOnDesktop(&rc)) {
|
|
ihwndJump = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
iRefresh++;
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID JerkDesktop(
|
|
INT xr,
|
|
INT yr,
|
|
HWND hwndFocus,
|
|
INT iReal)
|
|
{
|
|
VOID RefreshWinState(VOID);
|
|
RECT rc;
|
|
|
|
Working(&rc);
|
|
if (hwndFocus) {
|
|
#ifdef WIN16
|
|
SetActiveWindow(hwndFocus);
|
|
#else // WIN32
|
|
SetForegroundWindow(hwndFocus);
|
|
#endif // WIN16
|
|
GetWindowRect(hwndFocus, &rc);
|
|
GetCriticalPoint(&rc, &xr, &yr);
|
|
}
|
|
xr -= (xr + cxrDT * nxVDT) % cxrDT;
|
|
yr -= (yr + cyrDT * nyVDT) % cyrDT;
|
|
if (xr || yr) {
|
|
MoveChildren(-xr, -yr);
|
|
} else {
|
|
InvalidateRect(hwndTopdesk, &rc, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID RefreshWinState()
|
|
{
|
|
INT i, j;
|
|
RECT rc;
|
|
|
|
if (fBlockRefresh) {
|
|
return;
|
|
}
|
|
|
|
fInvalidated = FALSE;
|
|
if (cWindows == 0) {
|
|
ihwndJump = -2;
|
|
} else {
|
|
ihwndJump = -1; // RefreshEnumProc will set this if a new one is found.
|
|
}
|
|
iRefresh = 0;
|
|
EnumWindows((WNDENUMPROC)fpRefreshEnumProc, 0);
|
|
if (iRefresh != cWindows && iRefresh < MAX_REMEMBER) {
|
|
fInvalidated = TRUE;
|
|
cWindows = iRefresh;
|
|
}
|
|
//
|
|
// Remove any ghost links where the real window died.
|
|
//
|
|
for (i = 0; i < cGhosts; i++) {
|
|
j = FindRealLink(i);
|
|
if (j == -1) {
|
|
ghoststate[i].hwnd = 0;
|
|
ghoststate[i].style &= ~WISF_LINKED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If any new windows were discovered and were linked, jump to the first one found.
|
|
//
|
|
if (ihwndJump > -1) {
|
|
int x, y;
|
|
|
|
//
|
|
// Jerk the desktop to the new window.
|
|
//
|
|
GetBestGuessRect(&rc, &winstate[ihwndJump]);
|
|
GetCriticalPoint(&rc, &x, &y);
|
|
JerkDesktop(x, y, 0, -1);
|
|
fInvalidated = TRUE;
|
|
}
|
|
|
|
if (fInvalidated) {
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID ToggleFrameCtrls()
|
|
{
|
|
DWORD dwStyle;
|
|
INT mfT ;
|
|
|
|
mfT = pro.mfx; // swap these so that when frame controls
|
|
pro.mfx = pro.mfxAlt; // are changed we revert back to what we
|
|
pro.mfxAlt = mfT; // last had before recalcing.
|
|
|
|
mfT = pro.mfy;
|
|
pro.mfy = pro.mfyAlt;
|
|
pro.mfyAlt = mfT;
|
|
|
|
fFrameToggleSize = TRUE; // so WM_SIZE recalc is bypassed.
|
|
|
|
dwStyle = GetWindowLong(hwndTopdesk, GWL_STYLE);
|
|
pro.fShowFrameCtrls = !pro.fShowFrameCtrls;
|
|
if (pro.fShowFrameCtrls) {
|
|
SetWindowLong(hwndTopdesk, GWL_STYLE, dwStyle | WS_THICKFRAME | WS_DLGFRAME);
|
|
SetMenu(hwndTopdesk, hMenuTopdesk);
|
|
} else {
|
|
SetWindowLong(hwndTopdesk, GWL_STYLE, dwStyle & ~(WS_THICKFRAME | WS_DLGFRAME));
|
|
hMenuTopdesk = GetMenu(hwndTopdesk);
|
|
SetMenu(hwndTopdesk, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
HWND GetTopAppHwnd()
|
|
{
|
|
int i;
|
|
POINT pt;
|
|
RECT rc;
|
|
|
|
//
|
|
// return the topmost window who's centerpoint lies within the current
|
|
// desktop. (skip topdesk itself)
|
|
//
|
|
for (i = 0; i < cWindows; i++) {
|
|
if (winstate[i].hwnd == hwndTopdesk)
|
|
continue;
|
|
GetBestGuessRect(&rc, &winstate[i]);
|
|
pt.x = (rc.left + rc.right) / 2;
|
|
pt.y = (rc.top + rc.bottom) / 2;
|
|
if (PtInRect(&rcrDT, pt)) {
|
|
return(winstate[i].hwnd);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
VOID AlignWindow(
|
|
HWND hwnd,
|
|
BOOL fLeft,
|
|
BOOL fRight,
|
|
BOOL fTop,
|
|
BOOL fBottom)
|
|
{
|
|
RECT rc;
|
|
RECT rcClient;
|
|
int x, y;
|
|
LONG lStyle;
|
|
|
|
if (hwnd == 0) {
|
|
return;
|
|
}
|
|
GetWindowRect(hwnd, &rc);
|
|
GetClientRect(hwnd, &rcClient);
|
|
|
|
x = rc.left;
|
|
if (fLeft) {
|
|
x = 0;
|
|
} else if (fRight) {
|
|
x = cxrDT - (rc.right - rc.left);
|
|
}
|
|
|
|
y = rc.top;
|
|
if (fTop) {
|
|
y = 0;
|
|
} else if (fBottom) {
|
|
y = cyrDT - (rc.bottom - rc.top);
|
|
}
|
|
|
|
lStyle = GetWindowLong(hwnd, GWL_STYLE);
|
|
if (lStyle & WS_MAXIMIZE) {
|
|
if (lStyle & WS_THICKFRAME) {
|
|
if (cxrDT <= (rcClient.right - rcClient.left)) {
|
|
if (fLeft) {
|
|
x -= cxFrame;
|
|
} else if (fRight) {
|
|
x += cxFrame;
|
|
}
|
|
}
|
|
if (cyrDT <= (rcClient.bottom - rcClient.top)) {
|
|
if (fTop) {
|
|
y -= cyFrame;
|
|
} else if (fBottom) {
|
|
y += cyFrame;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MyMoveWindow(hwnd, x, y, rc.right - rc.left, rc.bottom - rc.top);
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
}
|
|
|
|
|
|
|
|
VOID NewGhostWindow(
|
|
LPTSTR pszTitle)
|
|
{
|
|
MYSTARTUPINFO *psi;
|
|
|
|
if (cGhosts < MAX_REMEMBER) {
|
|
cGhosts++;
|
|
for (psi = pStartupInfo; psi != NULL; psi = psi->next) {
|
|
if (!_tcsicmp(psi->pszTitle, pszTitle)) {
|
|
break;
|
|
}
|
|
}
|
|
if (psi == NULL) {
|
|
CreateStartupInfo(pszTitle, TEXT(""), TEXT(""), FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID CALLBACK ResetGhostState(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
UINT id,
|
|
DWORD time)
|
|
{
|
|
if (idResetGhostTimer) {
|
|
KillTimer(hwnd, idResetGhostTimer);
|
|
idResetGhostTimer = 0;
|
|
}
|
|
pro.iShowGhosts = PrevGhostState;
|
|
SaveGhostState();
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID SnapGhost(
|
|
INT i)
|
|
{
|
|
INT j;
|
|
|
|
if (winstate[i].hwnd == hwndTopdesk ||
|
|
winstate[i].style & WS_MINIMIZE) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// see if there exists a ghost we can link the window to.
|
|
//
|
|
if (!(winstate[i].style & WISF_LINKED)) {
|
|
for (j = 0; j < cGhosts; j++) {
|
|
if (ghoststate[j].hwnd == 0 &&
|
|
!_tcsicmp(ghoststate[j].szTitle, winstate[iRefresh].szTitle)
|
|
) {
|
|
//
|
|
// Link the ghost window with the real window and make the
|
|
// real window jump to the ghost's location and state.
|
|
//
|
|
winstate[iRefresh].style |= WISF_LINKED;
|
|
ghoststate[j].style |= WISF_LINKED;
|
|
ghoststate[j].hwnd = winstate[iRefresh].hwnd;
|
|
_tcscpy(ghoststate[j].szTitle, winstate[iRefresh].szTitle);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (winstate[i].style & WISF_LINKED) {
|
|
//
|
|
// update ghost
|
|
//
|
|
for (j = 0; j < cGhosts; j++) {
|
|
if (ghoststate[j].hwnd == winstate[i].hwnd) {
|
|
ghoststate[j] = winstate[i];
|
|
ghoststate[j].rc = winstate[i].rc;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// make a new ghost - don't snap minimized ghosts because we
|
|
// can't move them anyway.
|
|
//
|
|
if (winstate[i].hwnd != hwndTopdesk) {
|
|
NewGhostWindow(winstate[i].szTitle);
|
|
winstate[i].style |= WISF_LINKED;
|
|
ghoststate[cGhosts - 1] = winstate[i];
|
|
ghoststate[cGhosts - 1].rc = winstate[i].rc;
|
|
}
|
|
}
|
|
SaveGhostState();
|
|
PrevGhostState = pro.iShowGhosts;
|
|
pro.iShowGhosts = SG_ALL;
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
if (!idResetGhostTimer) {
|
|
idResetGhostTimer = SetTimer(NULL, 0, 1000, ResetGhostState);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID SnapGhosts()
|
|
{
|
|
INT i;
|
|
INT OrgGhostState;
|
|
|
|
OrgGhostState = pro.iShowGhosts;
|
|
for (i = 0; i < cWindows; i++) {
|
|
SnapGhost(i);
|
|
}
|
|
PrevGhostState = OrgGhostState;
|
|
}
|
|
|
|
|
|
MYSTARTUPINFO *FindStartupInfo(
|
|
INT iGhost)
|
|
{
|
|
MYSTARTUPINFO *psi;
|
|
|
|
//
|
|
// Locate matching startup info.
|
|
//
|
|
psi = pStartupInfo;
|
|
while (psi != NULL &&
|
|
_tcsicmp(ghoststate[iGhost].szTitle, psi->pszTitle)) {
|
|
psi = psi->next;
|
|
}
|
|
if (psi == NULL) {
|
|
psi = CreateStartupInfo(ghoststate[iGhost].szTitle, TEXT(""), TEXT(""), FALSE);
|
|
}
|
|
return(psi);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CommandMsg(WORD cmd)
|
|
{
|
|
INT i;
|
|
INT iReal, iGhost;
|
|
FARPROC lpfp;
|
|
INT dx = 0, dy = 0;
|
|
|
|
switch (cmd) {
|
|
case CMD_ABSOLUTE_VIEW:
|
|
if (pro.fRelative) {
|
|
// Rel-> Abs - puts HDT into center
|
|
oxrCDT -= oxrHDT;
|
|
oyrCDT -= oyrHDT;
|
|
oxrHDT = 0;
|
|
oyrHDT = 0;
|
|
pro.fRelative = !pro.fRelative;
|
|
goto repaint;
|
|
}
|
|
break;
|
|
|
|
case CMD_RELATIVE_VIEW:
|
|
if (!pro.fRelative) {
|
|
// Abs -> Rel - puts CDT into center
|
|
oxrHDT -= oxrCDT;
|
|
oyrHDT -= oyrCDT;
|
|
oxrCDT = 0;
|
|
oyrCDT = 0;
|
|
pro.fRelative = !pro.fRelative;
|
|
goto repaint;
|
|
}
|
|
break;
|
|
|
|
case CMD_TOGGLE_FRM_CTRLS:
|
|
ToggleFrameCtrls();
|
|
goto repaint;
|
|
|
|
case CMD_TOGGLE_GHOSTS:
|
|
switch (pro.iShowGhosts) {
|
|
case SG_NONE:
|
|
pro.iShowGhosts = SG_ALL;
|
|
break;
|
|
|
|
case SG_ALL:
|
|
pro.iShowGhosts = SG_PARTIAL;
|
|
break;
|
|
|
|
case SG_PARTIAL:
|
|
pro.iShowGhosts = SG_NONE;
|
|
break;
|
|
}
|
|
goto repaint;
|
|
|
|
case CMD_HIDE_GHOSTS:
|
|
pro.iShowGhosts = SG_NONE;
|
|
goto repaint;
|
|
|
|
case CMD_SHOW_GHOSTS:
|
|
pro.iShowGhosts = SG_ALL;
|
|
goto repaint;
|
|
|
|
case CMD_PARTIAL_GHOSTS:
|
|
pro.iShowGhosts = SG_PARTIAL;
|
|
goto repaint;
|
|
|
|
case CMD_STARTUPINFO:
|
|
fStartingAnApp = FALSE;
|
|
StartStartupInfo(pStartupInfo, 0, FALSE);
|
|
break;
|
|
|
|
case CMD_MAGNIFY:
|
|
if (pro.mfx > 0) {
|
|
pro.mfx--;
|
|
}
|
|
if (pro.mfy > 0) {
|
|
pro.mfy--;
|
|
}
|
|
CalcConversionFactors(TRUE);
|
|
goto repaint;
|
|
|
|
case CMD_MAGNIFY_VERT:
|
|
if (pro.mfy > 0) {
|
|
pro.mfy--;
|
|
}
|
|
goto repaint;
|
|
|
|
case CMD_MAGNIFY_HORZ:
|
|
if (pro.mfx > 0) {
|
|
pro.mfx--;
|
|
}
|
|
goto repaint;
|
|
|
|
case CMD_REDUCE:
|
|
if (cycDT > cycDTmin) {
|
|
pro.mfy++;
|
|
}
|
|
if (cxcDT > cxcDTmin) {
|
|
pro.mfx++;
|
|
}
|
|
CalcConversionFactors(TRUE);
|
|
goto repaint;
|
|
|
|
case CMD_REDUCE_VERT:
|
|
if (cycDT > cycDTmin) {
|
|
pro.mfy++;
|
|
}
|
|
goto repaint;
|
|
|
|
case CMD_REDUCE_HORZ:
|
|
if (cxcDT > cxcDTmin) {
|
|
pro.mfx++;
|
|
}
|
|
goto repaint;
|
|
|
|
case CMD_SNAPSHOT:
|
|
SnapGhosts();
|
|
goto repaint;
|
|
|
|
case CMD_ERASEGHOSTS:
|
|
if (cGhosts == 0) {
|
|
break;
|
|
}
|
|
cGhosts = 0;
|
|
for (i = 0; i < cWindows; i++) {
|
|
winstate[i].style &= ~WISF_LINKED;
|
|
}
|
|
SaveGhostState();
|
|
goto repaint;
|
|
|
|
case CMD_GATHER:
|
|
CommandMsg(CMD_GOHOME);
|
|
GatherWindows();
|
|
break;
|
|
|
|
case CMDP_SETHOME: // we use a seperate constant to avoid
|
|
// WM_INITMENU processing for the popup one.
|
|
JerkDesktop(PopupPt.x, PopupPt.y, (HWND)0, -1);
|
|
|
|
case CMD_SETHOME:
|
|
oxrHDT = oxrCDT = 0;
|
|
oyrHDT = oyrCDT = 0;
|
|
goto repaint;
|
|
|
|
case CMD_LL_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = -cyrDT * 4;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = -cxrDT * 4;
|
|
} else {
|
|
dx = -cxrDT;
|
|
dy = cyrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_LC_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = -cyrDT * 3;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = -cxrDT * 3;
|
|
} else {
|
|
dy = cyrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_LR_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = -cyrDT * 2;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = -cxrDT * 2;
|
|
} else {
|
|
dx = cxrDT;
|
|
dy = cyrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_CL_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = -cyrDT;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = -cxrDT;
|
|
} else {
|
|
dx = -cxrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_CR_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = cyrDT;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = cxrDT;
|
|
} else {
|
|
dx = cxrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_UL_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = cyrDT * 2;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = cxrDT * 2;
|
|
} else {
|
|
dx = -cxrDT;
|
|
dy = -cyrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_UC_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = cyrDT * 3;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = cxrDT * 3;
|
|
} else {
|
|
dy = -cyrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_UR_OF_HOME:
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // VERT
|
|
dy = cyrDT * 4;
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // HORZ
|
|
dx = cxrDT * 4;
|
|
} else {
|
|
dx = cxrDT;
|
|
dy = -cyrDT;
|
|
}
|
|
goto move_to_home;
|
|
|
|
case CMD_DISTRIBUTE:
|
|
for (iReal = 0; iReal < cWindows; iReal++) {
|
|
if (winstate[iReal].style & WISF_LINKED) {
|
|
iGhost = FindLinkedGhost(iReal);
|
|
if (iGhost > -1) {
|
|
DistributeWindow(iReal, iGhost);
|
|
} else {
|
|
winstate[iReal].style &= ~WISF_LINKED;
|
|
}
|
|
} else {
|
|
iGhost = FindLinkableGhost(iReal);
|
|
if (iGhost > -1) {
|
|
LinkWindows(iReal, iGhost, FALSE);
|
|
DistributeWindow(iReal, iGhost);
|
|
}
|
|
}
|
|
}
|
|
// fall through to go home
|
|
|
|
case CMD_GOHOME:
|
|
dx = 0;
|
|
dy = 0;
|
|
move_to_home:
|
|
if (pro.fRelative) {
|
|
MoveChildren(-oxrHDT - dx, -oyrHDT - dy);
|
|
} else {
|
|
MoveChildren(oxrCDT - dx, oyrCDT - dy);
|
|
}
|
|
repaint:
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
break;
|
|
|
|
case CMD_HELP:
|
|
WinHelp(hwndTopdesk, pszHelpFileName, HELP_INDEX, 0L);
|
|
break;
|
|
|
|
case CMD_COMMANDS:
|
|
WinHelp(hwndTopdesk, pszHelpFileName, HELP_INDEX, 3L);
|
|
break;
|
|
|
|
case CMD_EXIT:
|
|
WinHelp(hwndTopdesk, pszHelpFileName, HELP_QUIT, 0);
|
|
PostMessage(hwndTopdesk, WM_CLOSE, 0, 0L);
|
|
break;
|
|
|
|
case CMD_DTLEFT:
|
|
MoveChildren(cxrDT, 0);
|
|
break;
|
|
|
|
case CMD_DTRIGHT:
|
|
MoveChildren(-cxrDT, 0);
|
|
break;
|
|
|
|
case CMD_DTUP:
|
|
MoveChildren(0, cyrDT);
|
|
break;
|
|
|
|
case CMD_DTDOWN:
|
|
MoveChildren(0, -cyrDT);
|
|
break;
|
|
|
|
case CMD_MDLEFT:
|
|
AlignWindow(hwndTopdesk, 1, 0, 0, 0);
|
|
break;
|
|
|
|
case CMD_MDRIGHT:
|
|
AlignWindow(hwndTopdesk, 0, 1, 0, 0);
|
|
break;
|
|
|
|
case CMD_MDUP:
|
|
AlignWindow(hwndTopdesk, 0, 0, 1, 0);
|
|
break;
|
|
|
|
case CMD_MDDOWN:
|
|
AlignWindow(hwndTopdesk, 0, 0, 0, 1);
|
|
break;
|
|
|
|
case CMD_ALIGNLEFT:
|
|
AlignWindow(GetTopAppHwnd(), 1, 0, 0, 0);
|
|
break;
|
|
|
|
case CMD_ALIGNRIGHT:
|
|
AlignWindow(GetTopAppHwnd(), 0, 1, 0, 0);
|
|
break;
|
|
|
|
case CMD_ALIGNUP:
|
|
AlignWindow(GetTopAppHwnd(), 0, 0, 1, 0);
|
|
break;
|
|
|
|
case CMD_ALIGNDOWN:
|
|
AlignWindow(GetTopAppHwnd(), 0, 0, 0, 1);
|
|
break;
|
|
|
|
case CMD_ABOUT:
|
|
fBlockRefresh++;
|
|
lpfp = MakeProcInstance((FARPROC)AboutDlgProc, hInst);
|
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hwndTopdesk, (DLGPROC)lpfp);
|
|
FreeProcInstance(lpfp);
|
|
fBlockRefresh--;
|
|
break;
|
|
|
|
case CMD_CONFIG:
|
|
fBlockRefresh++;
|
|
lpfp = MakeProcInstance((FARPROC)ConfigDlgProc, hInst);
|
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_CONFIG), hwndTopdesk, (DLGPROC)lpfp);
|
|
FreeProcInstance(lpfp);
|
|
fBlockRefresh--;
|
|
break;
|
|
|
|
case CMDP_STARTUPINFO:
|
|
StartStartupInfo(FindStartupInfo(PopupGhostIndex), PopupGhostIndex, FALSE);
|
|
break;
|
|
|
|
case CMDP_DISTRIBUTE_GHOST:
|
|
DistributeWindow(-1, PopupGhostIndex);
|
|
InvalidateRect(hwndTopdesk, NULL, FALSE);
|
|
break;
|
|
|
|
case CMDP_DISTRIBUTE_REAL:
|
|
DistributeWindow(PopupRealIndex, -1);
|
|
InvalidateRect(hwndTopdesk, NULL, FALSE);
|
|
break;
|
|
|
|
case CMDP_START_GHOST:
|
|
StartGhostWindow(PopupGhostIndex);
|
|
break;
|
|
|
|
case CMDP_DESTROY_GHOST:
|
|
DeleteGhostWindow(PopupGhostIndex);
|
|
break;
|
|
|
|
case CMDP_UNLOCK_GHOST:
|
|
ghoststate[PopupGhostIndex].style &= ~WISF_FIXED;
|
|
SaveGhostState();
|
|
InvalidateRect(hwndTopdesk, NULL, FALSE);
|
|
break;
|
|
|
|
case CMDP_LOCK_GHOST:
|
|
ghoststate[PopupGhostIndex].style |= WISF_FIXED;
|
|
SaveGhostState();
|
|
InvalidateRect(hwndTopdesk, NULL, FALSE);
|
|
break;
|
|
|
|
case CMDP_JUMP_REAL:
|
|
JerkDesktop(PopupPt.x, PopupPt.y, PopuphwndFocus, PopupRealIndex);
|
|
break;
|
|
|
|
case CMDP_DESTROY_REAL:
|
|
SendMessage(winstate[PopupRealIndex].hwnd, WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case CMDP_UNLOCK_REAL:
|
|
winstate[PopupRealIndex].style &= ~WISF_FIXED;
|
|
InvalidateRect(hwndTopdesk, NULL, FALSE);
|
|
break;
|
|
|
|
case CMDP_LOCK_REAL:
|
|
winstate[PopupRealIndex].style |= WISF_FIXED;
|
|
InvalidateRect(hwndTopdesk, NULL, FALSE);
|
|
break;
|
|
|
|
case CMDP_SNAPSHOT_REAL:
|
|
SnapGhost(PopupRealIndex);
|
|
break;
|
|
|
|
case CMDP_SNAPSHOT_GHOST:
|
|
SnapGhost(FindLinkedGhost(PopupGhostIndex));
|
|
break;
|
|
|
|
case CMDP_JUMP_DESKTOP:
|
|
JerkDesktop(PopupPt.x, PopupPt.y, (HWND)0, -1);
|
|
break;
|
|
|
|
case CMD_TOPMOST:
|
|
pro.fAlwaysOnTop = !pro.fAlwaysOnTop;
|
|
SetWindowPos(hwndTopdesk,
|
|
pro.fAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0,
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
break;
|
|
|
|
#ifdef DEBUG
|
|
case CMD_DUMP_ALL:
|
|
{
|
|
_ftprintf(hfDbgOut, TEXT("Globals:\n"));
|
|
_ftprintf(hfDbgOut, TEXT("\tfBlockRefresh = %d\n"), fBlockRefresh);
|
|
_ftprintf(hfDbgOut, TEXT("\tfFrameToggleSize = %d\n"), fFrameToggleSize);
|
|
_ftprintf(hfDbgOut, TEXT("\tfInvalidated = %d\n"), fInvalidated);
|
|
_ftprintf(hfDbgOut, TEXT("\tfStarted = %d\n"), fStarted);
|
|
_ftprintf(hfDbgOut, TEXT("\thwndFocus = %lx\n"), hwndFocus);
|
|
_ftprintf(hfDbgOut, TEXT("\tiStartGhost = %d\n"), iStartGhost);
|
|
_ftprintf(hfDbgOut, TEXT("\tcGhosts = %d\n"), cGhosts);
|
|
_ftprintf(hfDbgOut, TEXT("\tcWindows = %d\n"), cWindows);
|
|
_ftprintf(hfDbgOut, TEXT("\tcxc = %d\n"), cxc);
|
|
_ftprintf(hfDbgOut, TEXT("\tcxcDT = %d\n"), cxcDT);
|
|
_ftprintf(hfDbgOut, TEXT("\tcxcDTmin = %d\n"), cxcDTmin);
|
|
_ftprintf(hfDbgOut, TEXT("\tcxFrame = %d\n"), cxFrame);
|
|
_ftprintf(hfDbgOut, TEXT("\tcxrDT = %d\n"), cxrDT);
|
|
_ftprintf(hfDbgOut, TEXT("\tcyc = %d\n"), cyc);
|
|
_ftprintf(hfDbgOut, TEXT("\tcycDT = %d\n"), cycDT);
|
|
_ftprintf(hfDbgOut, TEXT("\tcycDTmin = %d\n"), cycDTmin);
|
|
_ftprintf(hfDbgOut, TEXT("\tcyFrame = %d\n"), cyFrame);
|
|
_ftprintf(hfDbgOut, TEXT("\tcyrDT = %d\n"), cyrDT);
|
|
_ftprintf(hfDbgOut, TEXT("\tiRefresh = %d\n"), iRefresh);
|
|
_ftprintf(hfDbgOut, TEXT("\tihwndJump = %d\n"), ihwndJump);
|
|
_ftprintf(hfDbgOut, TEXT("\tnxVDT = %d\n"), nxVDT);
|
|
_ftprintf(hfDbgOut, TEXT("\tnyVDT = %d\n"), nyVDT);
|
|
_ftprintf(hfDbgOut, TEXT("\toxcODT = %d\n"), oxcODT);
|
|
_ftprintf(hfDbgOut, TEXT("\toxrCDT = %d\n"), oxrCDT);
|
|
_ftprintf(hfDbgOut, TEXT("\toxrHDT = %d\n"), oxrHDT);
|
|
_ftprintf(hfDbgOut, TEXT("\toycODT = %d\n"), oycODT);
|
|
_ftprintf(hfDbgOut, TEXT("\toyrCDT = %d\n"), oyrCDT);
|
|
_ftprintf(hfDbgOut, TEXT("\toyrHDT = %d\n"), oyrHDT);
|
|
_ftprintf(hfDbgOut, TEXT("\trcrDT = %d\n"), rcrDT);
|
|
_ftprintf(hfDbgOut, TEXT("\trcrMS = %d\n"), rcrMS);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fShift = %d\n"), pro.fShift);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fAlt = %d\n"), pro.fAlt);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fControl = %d\n"), pro.fControl);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.vkey = %d\n"), pro.vkey);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.mfx = %d\n"), pro.mfx);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.mfy = %d\n"), pro.mfy);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.mfxAlt = %d\n"), pro.mfxAlt);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.mfyAlt = %d\n"), pro.mfyAlt);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.x = %d\n"), pro.x);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.y = %d\n"), pro.y);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.cx = %d\n"), pro.cx);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.cy = %d\n"), pro.cy);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.iShowGhosts = %d\n"), pro.iShowGhosts);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fRelative = %d\n"), pro.fRelative);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fDistOnStart = %d\n"), pro.fDistOnStart);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fShowFrameCtrls = %d\n"), pro.fShowFrameCtrls);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fAutoAdj = %d\n"), pro.fAutoAdj);
|
|
_ftprintf(hfDbgOut, TEXT("\tpro.fAlwaysOnTop = %d\n"), pro.fAlwaysOnTop);
|
|
_ftprintf(hfDbgOut, TEXT("winstate:\n"));
|
|
for (i = 0; i < cWindows; i++) {
|
|
_ftprintf(hfDbgOut, TEXT(" (%d)\n"), i);
|
|
_ftprintf(hfDbgOut, TEXT(" rc = (%d - %d, %d - %d)\n"),
|
|
winstate[i].rc.left,
|
|
winstate[i].rc.right,
|
|
winstate[i].rc.top,
|
|
winstate[i].rc.bottom
|
|
);
|
|
_ftprintf(hfDbgOut, TEXT(" style = %lx\n"), winstate[i].style);
|
|
_ftprintf(hfDbgOut, TEXT(" hwnd = %lx\n"), winstate[i].hwnd);
|
|
_ftprintf(hfDbgOut, TEXT(" title = %s\n"), winstate[i].szTitle);
|
|
}
|
|
_ftprintf(hfDbgOut, TEXT("ghoststate:\n"));
|
|
for (i = 0; i < cGhosts; i++) {
|
|
_ftprintf(hfDbgOut, TEXT(" (%d)\n"), i);
|
|
_ftprintf(hfDbgOut, TEXT(" rc = (%d - %d, %d - %d)\n"),
|
|
ghoststate[i].rc.left,
|
|
ghoststate[i].rc.right,
|
|
ghoststate[i].rc.top,
|
|
ghoststate[i].rc.bottom
|
|
);
|
|
_ftprintf(hfDbgOut, TEXT(" style = %lx\n"), ghoststate[i].style);
|
|
_ftprintf(hfDbgOut, TEXT(" hwnd = %lx\n"), ghoststate[i].hwnd);
|
|
_ftprintf(hfDbgOut, TEXT(" title = %s\n"), ghoststate[i].szTitle);
|
|
}
|
|
}
|
|
break;
|
|
#endif // DEBUG
|
|
|
|
default:
|
|
return(FALSE);
|
|
break;
|
|
}
|
|
RefreshWinState();
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID MyDrawText(
|
|
HDC hdc,
|
|
LPTSTR psz,
|
|
LPRECT prc,
|
|
LONG clrFgnd,
|
|
LONG clrBkgnd,
|
|
WORD flCmd)
|
|
{
|
|
SetTextColor(hdc, pro.ahbr[clrFgnd].color);
|
|
SetBkColor(hdc, pro.ahbr[clrBkgnd].color);
|
|
DrawText(hdc, psz, -1, prc, flCmd);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* maps a normal window rect (in desktop coordinates) to the proper size
|
|
* for the topdesk client and draws it.
|
|
*/
|
|
VOID DrawWindowRect(
|
|
HWND hwnd,
|
|
PRECT prc,
|
|
DWORD FillColor,
|
|
DWORD FrameColor,
|
|
BOOL fMaximized)
|
|
{
|
|
TCHAR sz[MAX_SZTITLE];
|
|
|
|
rRect2cRect(prc);
|
|
if (FillColor)
|
|
FillRect(hdcDraw, prc, pro.ahbr[FillColor].hbr);
|
|
GetModifiedWindowTitle(hwnd, sz);
|
|
InflateRect(prc, -2, -2);
|
|
MyDrawText(hdcDraw, sz, prc, WINDOWTEXT, FillColor,
|
|
DT_LEFT | DT_TOP | DT_WORDBREAK);
|
|
if (fMaximized) {
|
|
MyDrawText(hdcDraw, GetResString(IDS_MAX), prc, WINDOWTEXT, FillColor,
|
|
DT_LEFT | DT_BOTTOM | DT_SINGLELINE);
|
|
}
|
|
InflateRect(prc, 2, 2);
|
|
FrameRect(hdcDraw, prc, pro.ahbr[FrameColor].hbr);
|
|
}
|
|
|
|
|
|
|
|
VOID DottedLine(
|
|
HDC hdc,
|
|
INT x1,
|
|
INT y1,
|
|
INT x2,
|
|
INT y2,
|
|
DWORD color)
|
|
{
|
|
HPEN hPenSave, hPen;
|
|
|
|
hPen = CreatePen(PS_DOT, 1, pro.ahbr[color].color);
|
|
hPenSave = SelectObject(hdc, hPen);
|
|
MoveToEx(hdc, x1, y1, NULL);
|
|
LineTo(hdc, x2, y2);
|
|
DeleteObject(SelectObject(hdc, hPenSave));
|
|
}
|
|
|
|
|
|
|
|
VOID TopDeskPaint(
|
|
HDC hdc,
|
|
RECT rc)
|
|
{
|
|
RECT rcChild;
|
|
INT x, y;
|
|
INT i;
|
|
HFONT hfOld;
|
|
|
|
hdcDraw = hdc;
|
|
hfOld = SelectObject(hdc, hMyFont);
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
cxc = rc.right;
|
|
cyc = rc.bottom;
|
|
CalcConversionFactors(FALSE);
|
|
|
|
FillRect(hdc, &rc, pro.ahbr[SPACECOLOR].hbr);
|
|
|
|
if (pro.mfx > 0) {
|
|
|
|
for (x = oxcODT; x < cxc; x += cxcDT) {
|
|
DottedLine(hdc, x, 0, x, cyc, GRIDCOLOR);
|
|
}
|
|
for (x = oxcODT - cxcDT; x > 0; x -= cxcDT) {
|
|
DottedLine(hdc, x, 0, x, cyc, GRIDCOLOR);
|
|
}
|
|
}
|
|
if (pro.mfy > 0) {
|
|
for (y = oycODT; y < cyc; y += cycDT) {
|
|
DottedLine(hdc, 0, y, cxc, y, GRIDCOLOR);
|
|
}
|
|
for (y = oycODT - cycDT ; y > 0; y -= cycDT) {
|
|
DottedLine(hdc, 0, y, cxc, y, GRIDCOLOR);
|
|
}
|
|
}
|
|
|
|
rcChild = rcrDT;
|
|
DrawWindowRect(hwndDT, &rcChild, DESKFILLCOLOR, DESKFILLCOLOR, FALSE);
|
|
rcChild = rcrDT;
|
|
if (pro.fRelative) {
|
|
OffsetRect(&rcChild, oxrHDT, oyrHDT);
|
|
} else {
|
|
OffsetRect(&rcChild, -oxrCDT, -oyrCDT);
|
|
}
|
|
DrawWindowRect(hwndDT, &rcChild, 0L, DESKFRAMECOLOR, FALSE);
|
|
InflateRect(&rcChild, -1, -1);
|
|
FrameRect(hdcDraw, &rcChild, pro.ahbr[DESKFRAMECOLOR].hbr);
|
|
InflateRect(&rcChild, -1, -1);
|
|
|
|
MyDrawText(hdcDraw, TEXT("5"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, -cycDT);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, -cxcDT, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, -cxcDT, 0);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("4"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, cycDT * 3);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, cxcDT * 3, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, 0, -cycDT);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("7"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, cycDT);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, cxcDT, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, cxcDT, 0);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("8"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, cycDT);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, cxcDT, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, cxcDT, 0);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("9"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, -cycDT * 3);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, -cxcDT * 3, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, 0, cycDT);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("6"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, -cycDT * 3);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, -cxcDT * 3, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, 0, cycDT);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("3"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, -cycDT);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, -cxcDT, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, -cxcDT, 0);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("2"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (pro.mfx == 0 && pro.mfy != 0) { // Vert
|
|
OffsetRect(&rcChild, 0, -cycDT);
|
|
} else if (pro.mfx != 0 && pro.mfy == 0) { // Horz
|
|
OffsetRect(&rcChild, -cxcDT, 0);
|
|
} else {
|
|
OffsetRect(&rcChild, -cxcDT, 0);
|
|
}
|
|
MyDrawText(hdcDraw, TEXT("1"), &rcChild, GRIDCOLOR, SPACECOLOR, DT_RIGHT | DT_BOTTOM | DT_SINGLELINE);
|
|
|
|
if (cWindows) {
|
|
for (i = cWindows - 1; i >= 0; i--) {
|
|
if (winstate[i].hwnd == hwndTopdesk) {
|
|
continue;
|
|
}
|
|
|
|
// Draw existing window
|
|
|
|
GetBestGuessRect(&rcChild, &winstate[i]);
|
|
DrawWindowRect(winstate[i].hwnd, &rcChild,
|
|
WINDOWFILLCOLOR,
|
|
(winstate[i].style & (WISF_FIXED | WS_MINIMIZE) ? FIXEDFRAMECOLOR : WINDOWFRAMECOLOR),
|
|
winstate[i].style & WS_MAXIMIZE);
|
|
}
|
|
}
|
|
|
|
if ((pro.iShowGhosts != SG_NONE) && cGhosts) {
|
|
for (i = cGhosts - 1; i >= 0; i--) {
|
|
if ((pro.iShowGhosts == SG_ALL) || !(ghoststate[i].style & WISF_LINKED)) {
|
|
/*
|
|
* Draw ghost window
|
|
*/
|
|
rcChild = ghoststate[i].rc;
|
|
rRect2cRect(&rcChild);
|
|
InflateRect(&rcChild, -2, -2);
|
|
MyDrawText(hdc, ghoststate[i].szTitle,
|
|
&rcChild, GHOSTTEXTCOLOR, SPACECOLOR,
|
|
DT_LEFT | DT_TOP | DT_WORDBREAK);
|
|
if (ghoststate[i].style & WS_MAXIMIZE) {
|
|
MyDrawText(hdcDraw, GetResString(IDS_MAX), &rcChild,
|
|
GHOSTTEXTCOLOR, SPACECOLOR,
|
|
DT_LEFT | DT_BOTTOM | DT_SINGLELINE);
|
|
}
|
|
InflateRect(&rcChild, 2, 2);
|
|
FrameRect(hdc, &rcChild, pro.ahbr[ghoststate[i].style & WISF_FIXED ?
|
|
FIXEDFRAMECOLOR : GHOSTFRAMECOLOR].hbr);
|
|
}
|
|
}
|
|
}
|
|
|
|
SelectObject(hdc, hfOld);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* This routine returns the hwnd of the window associated with the given point.
|
|
* If the window isn't real, 0 is returned.
|
|
*
|
|
* *pwType is filled with an apropriate HTY_ value to indicat what was hit.
|
|
* *pi is the index into the winstate (hwnd returnd) or ghoststate (hwnd is 0)
|
|
* array.
|
|
* *prc is filled with the rectangle of the window hit.
|
|
*/
|
|
HWND MyWindowFromPt(
|
|
LPPOINT pptr, // Real Desktop coordinates
|
|
UINT *pwType,
|
|
PRECT prc,
|
|
INT *pi,
|
|
BOOL fSkipGhosts) // set if we don't want to hit a ghost.
|
|
{
|
|
INT i;
|
|
RECT rc;
|
|
|
|
/*
|
|
* If ghosts are showing check the ghoststate array for a hit first
|
|
* since ghosts are always on top.
|
|
*/
|
|
if ((pro.iShowGhosts != SG_NONE) && cGhosts && !fSkipGhosts) {
|
|
for (i = 0; i < cGhosts; i++) {
|
|
if ((pro.iShowGhosts == SG_PARTIAL) && ghoststate[i].style & WISF_LINKED) {
|
|
continue;
|
|
}
|
|
if (PtInRect(&ghoststate[i].rc, *pptr)) {
|
|
*pwType = HTY_GHOST;
|
|
*prc = ghoststate[i].rc;
|
|
if (pi != NULL) {
|
|
*pi = i;
|
|
}
|
|
return(ghoststate[i].hwnd);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* scan the winstate array for a hit
|
|
*/
|
|
for (i = 0; i < cWindows; i++) {
|
|
GetBestGuessRect(&rc, &winstate[i]);
|
|
if (PtInRect(&rc, *pptr)) {
|
|
if (winstate[i].hwnd == hwndTopdesk) {
|
|
continue;
|
|
}
|
|
*pwType = HTY_REAL;
|
|
*prc = rc;
|
|
if (pi != NULL) {
|
|
*pi = i;
|
|
}
|
|
return(winstate[i].hwnd);
|
|
}
|
|
}
|
|
/*
|
|
* Check the current desktop
|
|
*/
|
|
if (pro.fRelative) {
|
|
SetRect(prc, oxrCDT, oyrCDT, oxrCDT + cxrDT, oyrCDT + cyrDT);
|
|
} else {
|
|
SetRect(prc, -oxrHDT, -oyrHDT, -oxrHDT + cxrDT, -oyrHDT + cyrDT);
|
|
}
|
|
if (PtInRect(prc, *pptr)) {
|
|
*pwType = HTY_DESKTOP;
|
|
return(hwndDT);
|
|
}
|
|
/*
|
|
* Check for the home desktop
|
|
*/
|
|
if (pro.fRelative) {
|
|
SetRect(prc, oxrHDT, oyrHDT, oxrHDT + cxrDT, oyrHDT + cyrDT);
|
|
} else {
|
|
SetRect(prc, -oxrCDT, -oyrCDT, -oxrCDT + cxrDT, -oyrCDT + cyrDT);
|
|
}
|
|
if (PtInRect(prc, *pptr)) {
|
|
*pwType = HTY_HOME;
|
|
return(0);
|
|
}
|
|
|
|
*pwType = HTY_NONE;
|
|
return(0);
|
|
}
|
|
|
|
|
|
VOID TrackWindow(
|
|
INT xc,
|
|
INT yc)
|
|
{
|
|
POINT pt;
|
|
INT xCrit, yCrit;
|
|
UINT wType;
|
|
RECT rc, rcClient;
|
|
TRACKINFO ti;
|
|
INT width, height, i, xOrg, yOrg;
|
|
HWND hwnd;
|
|
BOOL fDesktopGrid, fLocked;
|
|
|
|
ti.ptOrg.x = xc;
|
|
ti.ptOrg.y = yc;
|
|
pt.x = xc2xr(xc);
|
|
pt.y = yc2yr(yc);
|
|
hwnd = MyWindowFromPt(&pt, &wType, &rc, &i, FALSE);
|
|
if (wType == HTY_NONE) {
|
|
/*
|
|
* No hit means we want to move the Topdesk window directly
|
|
*/
|
|
SendMessage(hwndTopdesk, WM_NCLBUTTONDOWN, HTCAPTION,
|
|
MAKELONG((SHORT)pt.x, (SHORT)pt.y));
|
|
return;
|
|
}
|
|
|
|
if (wType == HTY_REAL && winstate[i].style & WS_MINIMIZE) {
|
|
return; // can't drag minimized windows.
|
|
}
|
|
|
|
fDesktopGrid = (wType & (HTY_DESKTOP | HTY_HOME)) ||
|
|
(wType == HTY_REAL && winstate[i].style & WS_MAXIMIZE) ||
|
|
(GetKeyState(VK_CONTROL) & 0x8000);
|
|
|
|
fLocked = (wType & HTY_REAL && winstate[i].style & WISF_FIXED) ||
|
|
(wType & HTY_GHOST && ghoststate[i].style & WISF_FIXED);
|
|
|
|
if (fLocked && fDesktopGrid) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Now let the user drag the ghost or real or desktop or home window.
|
|
*/
|
|
width = rc.right - rc.left;
|
|
height = rc.bottom - rc.top;
|
|
GetCriticalPoint(&rc, &xCrit, &yCrit);
|
|
xCrit -= rc.left;
|
|
yCrit -= rc.top;
|
|
xOrg = rc.left;
|
|
yOrg = rc.top;
|
|
rRect2cRect(&rc);
|
|
ti.cxBorder = 2;
|
|
ti.cyBorder = 2;
|
|
ti.cxGrid = fDesktopGrid ? cxcDT : 1;
|
|
ti.cyGrid = fDesktopGrid ? cycDT : 1;
|
|
ti.cxKeyboard = ti.cxGrid;
|
|
ti.cyKeyboard = ti.cyGrid;
|
|
ti.rcTrack = rc;
|
|
GetClientRect(hwndTopdesk, &rcClient);
|
|
if (fLocked) {
|
|
/*
|
|
* Don't allow locked windows to be tracked off of the current
|
|
* desktop.
|
|
*/
|
|
ti.rcBoundary = rcrDT;
|
|
ti.rcBoundary.left -= xCrit - 1;
|
|
ti.rcBoundary.right += (width - xCrit) - 1;
|
|
ti.rcBoundary.top -= yCrit - 1;
|
|
ti.rcBoundary.bottom += (height - yCrit) - 1;
|
|
rRect2cRect(&ti.rcBoundary);
|
|
IntersectRect(&ti.rcBoundary, &ti.rcBoundary, &rcClient);
|
|
} else {
|
|
ti.rcBoundary = rcClient;
|
|
}
|
|
ti.ptMinTrackSize.x = 0;
|
|
ti.ptMinTrackSize.y = 0;
|
|
ti.fs = TF_MOVE | TF_ALLINBOUNDARY | TF_GRID | TF_SETPOINTERPOS;
|
|
if (hwnd == hwndTopdesk) {
|
|
ti.rcBoundary = rcrDT;
|
|
rRect2cRect(&ti.rcBoundary);
|
|
}
|
|
if (TrackRect(hInst, hwndTopdesk, &ti)) {
|
|
if (!EqualRect(&rc, &ti.rcTrack)) {
|
|
|
|
/*
|
|
* it has moved, update our database.
|
|
*/
|
|
cRect2rRect(&ti.rcTrack);
|
|
|
|
if (fDesktopGrid) {
|
|
int dx, dy;
|
|
|
|
dx = ti.rcTrack.left - xOrg;
|
|
if (dx > 0) {
|
|
/*
|
|
* round dx to an integral of cxrDT.
|
|
*/
|
|
dx = ((dx + (cxrDT >> 1)) / cxrDT) * cxrDT;
|
|
} else if (dx < 0) {
|
|
/*
|
|
* round dx to an integral of cxrDT.
|
|
*/
|
|
dx = -(((-dx + (cxrDT >> 1)) / cxrDT) * cxrDT);
|
|
}
|
|
dy = ti.rcTrack.top - yOrg;
|
|
if (dy > 0) {
|
|
/*
|
|
* round dy to an integral of cyrDT.
|
|
*/
|
|
dy = ((dy + (cyrDT >> 1)) / cyrDT) * cyrDT;
|
|
} else if (dy < 0) {
|
|
/*
|
|
* round dy to an integral of cyrDT.
|
|
*/
|
|
dy = -(((-dy + (cyrDT >> 1)) / cyrDT) * cyrDT);
|
|
}
|
|
ti.rcTrack.left = xOrg + dx;
|
|
ti.rcTrack.top = yOrg + dy;
|
|
ti.rcTrack.right = ti.rcTrack.left + width;
|
|
ti.rcTrack.bottom = ti.rcTrack.top + height;
|
|
}
|
|
|
|
if (wType & HTY_DESKTOP) {
|
|
MoveChildren(-ti.rcTrack.left, -ti.rcTrack.top);
|
|
} else if (wType & HTY_REAL) {
|
|
MyMoveWindow(hwnd, ti.rcTrack.left, ti.rcTrack.top, width, height);
|
|
} else if (wType & HTY_GHOST) {
|
|
ghoststate[i].rc = ti.rcTrack;
|
|
SaveGhostState();
|
|
} else if (wType & HTY_HOME) {
|
|
if (pro.fRelative) {
|
|
oxrHDT = ti.rcTrack.left;
|
|
oyrHDT = ti.rcTrack.top;
|
|
} else {
|
|
oxrCDT = -ti.rcTrack.left;
|
|
oyrCDT = -ti.rcTrack.top;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID MultiStart(
|
|
INT xc,
|
|
INT yc)
|
|
{
|
|
TRACKINFO ti;
|
|
INT iGhost;
|
|
RECT rc;
|
|
|
|
ti.cxGrid = 1;
|
|
ti.cyGrid = 1;
|
|
ti.cxBorder = 2;
|
|
ti.cyBorder = 2;
|
|
ti.cxKeyboard = 1;
|
|
ti.cyKeyboard = 1;
|
|
ti.rcTrack.left = ti.rcTrack.right = xc;
|
|
ti.rcTrack.top = ti.rcTrack.bottom = yc;
|
|
GetClientRect(hwndTopdesk, &ti.rcBoundary);
|
|
ti.ptMinTrackSize.x = -ti.rcBoundary.right;
|
|
ti.ptMinTrackSize.y = -ti.rcBoundary.bottom;
|
|
ti.fs = TF_RUBBERBAND | TF_ALLINBOUNDARY;
|
|
TrackRect(hInst, hwndTopdesk, &ti);
|
|
cRect2rRect(&ti.rcTrack);
|
|
rcrMS = ti.rcTrack;
|
|
fStartingAnApp = TRUE;
|
|
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
|
|
if (ghoststate[iGhost].hwnd == 0 &&
|
|
IntersectRect(&rc, &ghoststate[iGhost].rc, &rcrMS)) {
|
|
StartStartupInfo(FindStartupInfo(iGhost), iGhost, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* filched from progman... yeah, that's the ticket! */
|
|
BOOL ExecProgram(
|
|
LPTSTR lpszPath,
|
|
LPTSTR lpDir,
|
|
LPTSTR lpTitle)
|
|
{
|
|
LPTSTR lpP;
|
|
HINSTANCE hRet;
|
|
|
|
/* skip leading spaces
|
|
*/
|
|
while (*lpszPath == TEXT(' '))
|
|
lpszPath++;
|
|
|
|
/* skip past path
|
|
*/
|
|
lpP = (LPTSTR)LocalAlloc(0, (_tcslen(lpszPath) + 1) * sizeof(TCHAR));
|
|
if (lpP == NULL) {
|
|
return(0);
|
|
}
|
|
_tcscpy(lpP, lpszPath);
|
|
lpszPath = lpP;
|
|
|
|
for (; *lpP && *lpP != TEXT(' ';) lpP++)
|
|
;
|
|
|
|
/* if stuff on end, separate it
|
|
*/
|
|
if (*lpP)
|
|
*lpP++ = 0;
|
|
|
|
hRet = RealShellExecute(hwndTopdesk, NULL, lpszPath, lpP,
|
|
lpDir, NULL, lpTitle, NULL, SW_SHOW, NULL);
|
|
LocalFree(lpszPath);
|
|
return((DWORD)hRet >= 32);
|
|
}
|
|
|
|
|
|
|
|
VOID StartStartupInfo(
|
|
MYSTARTUPINFO *psi,
|
|
int iGhost,
|
|
BOOL fTryStartFirst)
|
|
{
|
|
FARPROC lpfp;
|
|
RECT rc;
|
|
|
|
if (cGhosts == 0) {
|
|
return; // can't look at ghost properties if there are no ghosts.
|
|
}
|
|
//
|
|
// come here if startup failed or we have a new entry or user wants
|
|
// to edit the entry.
|
|
//
|
|
lpfp = MakeProcInstance((FARPROC)StartupDlgProc, hInst);
|
|
|
|
if (fTryStartFirst) {
|
|
goto Startit;
|
|
}
|
|
|
|
while (psi != NULL) {
|
|
|
|
fBlockRefresh++;
|
|
psi = (MYSTARTUPINFO *)DialogBoxParam(hInst,
|
|
MAKEINTRESOURCE(IDD_STARTUP), hwndTopdesk,
|
|
(DLGPROC)lpfp, (LONG)(LPTSTR)psi);
|
|
fBlockRefresh--;
|
|
|
|
if (psi == NULL) {
|
|
break;
|
|
}
|
|
|
|
Startit:
|
|
|
|
//
|
|
// if iGhost doesn't match psi, find an apropriate ghost
|
|
//
|
|
if (_tcsicmp(ghoststate[iGhost].szTitle, psi->pszTitle)) {
|
|
for (iGhost = 0; iGhost < cGhosts; iGhost++) {
|
|
if (!_tcsicmp(ghoststate[iGhost].szTitle, psi->pszTitle)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Jerk the desktop to where the ghost is so if the window spawns
|
|
// other windows during startup, it doesn't put those guys
|
|
// somewhere in limbo.
|
|
//
|
|
if (iGhost < cGhosts && pro.fDistOnStart) {
|
|
int x, y;
|
|
|
|
GetCriticalPoint(&ghoststate[iGhost].rc, &x, &y);
|
|
JerkDesktop(x, y, NULL, -1);
|
|
}
|
|
|
|
SetCurrentDirectory(psi->pszWorkDir);
|
|
Working(&rc);
|
|
// if (WinExec(psi->pszStartup, SW_SHOW) < 32) {
|
|
if (!ExecProgram(psi->pszStartup, psi->pszWorkDir, psi->pszTitle)) {
|
|
MessageBeep(0);
|
|
} else {
|
|
iStartGhost = iGhost;
|
|
if (psi->fSetTitle) {
|
|
pszSetTitle = psi->pszTitle;
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
FreeProcInstance(lpfp);
|
|
RefreshWinState();
|
|
SaveProfile(); // so startup info gets updated.
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID StartGhostWindow(
|
|
INT iGhost)
|
|
{
|
|
BOOL fNew = FALSE;
|
|
INT iReal;
|
|
|
|
fStartingGhost = TRUE;
|
|
/*
|
|
* See if ghost's real window already exists - if so just switch to it.
|
|
*/
|
|
if (ghoststate[iGhost].style & WISF_LINKED) {
|
|
iReal = FindLinkedReal(iGhost);
|
|
if (iReal > -1) {
|
|
int x, y;
|
|
|
|
DistributeWindow(iReal, iGhost);
|
|
GetCriticalPoint(&ghoststate[iGhost].rc, &x, &y);
|
|
JerkDesktop(x, y, winstate[iReal].hwnd, iReal);
|
|
fStartingGhost = FALSE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
fStartingAnApp = TRUE;
|
|
StartStartupInfo(FindStartupInfo(iGhost), iGhost, TRUE);
|
|
fStartingGhost = FALSE;
|
|
}
|
|
|
|
|
|
|
|
UINT AppendPopupMenuItems(
|
|
HMENU hMenu,
|
|
UINT wType,
|
|
INT i,
|
|
BOOL fFirstTime)
|
|
{
|
|
TCHAR szT[MAX_SZTITLE * 2];
|
|
UINT Count = 0;
|
|
static BOOL fAppendedGhostMove;
|
|
|
|
if (fFirstTime) {
|
|
fAppendedGhostMove = FALSE;
|
|
}
|
|
if (wType == HTY_GHOST) {
|
|
if (ghoststate[i].hwnd &&
|
|
!EqualRect(&ghoststate[i].rc, &winstate[FindRealLink(i)].rc)) {
|
|
if (!fAppendedGhostMove) {
|
|
wsprintf(szT, GetResString(IDS_MOVETOGHOSTLOC), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_DISTRIBUTE_GHOST, szT);
|
|
Count++;
|
|
wsprintf(szT, GetResString(IDS_MOVEGHOSTTO), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_SNAPSHOT_GHOST, szT);
|
|
Count++;
|
|
fAppendedGhostMove = TRUE;
|
|
}
|
|
} else if (FindLinkedGhost(i) == -1) {
|
|
wsprintf(szT, GetResString(IDS_STARTGHOST), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_START_GHOST, szT);
|
|
Count++;
|
|
}
|
|
wsprintf(szT, GetResString(IDS_DESTROYGHOST), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_DESTROY_GHOST, szT);
|
|
Count++;
|
|
if (ghoststate[i].style & WISF_FIXED) {
|
|
wsprintf(szT, GetResString(IDS_UNLOCKGHOST), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_UNLOCK_GHOST, szT);
|
|
Count++;
|
|
} else if (IsCriticalPointOnDesktop(&ghoststate[i].rc)) {
|
|
wsprintf(szT, GetResString(IDS_LOCKGHOST), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_LOCK_GHOST, szT);
|
|
Count++;
|
|
}
|
|
wsprintf(szT, GetResString(IDS_PROPERTIES), ghoststate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_STARTUPINFO, szT);
|
|
Count++;
|
|
} else if (wType == HTY_REAL) {
|
|
wsprintf(szT, GetResString(IDS_JUMPTO), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_JUMP_REAL, szT);
|
|
Count++;
|
|
|
|
if (!(winstate[i].style & WS_MINIMIZE) && FindLinkedGhost(i) != -1) {
|
|
if (!EqualRect(&winstate[i].rc, &ghoststate[FindLinkedGhost(i)].rc)) {
|
|
if (!fAppendedGhostMove) {
|
|
wsprintf(szT, GetResString(IDS_MOVETOGHOSTLOC), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_DISTRIBUTE_REAL, szT);
|
|
Count++;
|
|
wsprintf(szT, GetResString(IDS_MOVEGHOSTTO), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_SNAPSHOT_REAL, szT);
|
|
Count++;
|
|
}
|
|
fAppendedGhostMove = TRUE;
|
|
}
|
|
} else if (!(winstate[i].style & WS_MINIMIZE)) {
|
|
wsprintf(szT, GetResString(IDS_CREATEGHOST), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_SNAPSHOT_REAL, szT);
|
|
Count++;
|
|
}
|
|
if (!(winstate[i].style & WS_MINIMIZE) && winstate[i].style & WISF_FIXED) {
|
|
wsprintf(szT, GetResString(IDS_UNLOCKWINDOW), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_UNLOCK_REAL, szT);
|
|
Count++;
|
|
} else if (!(winstate[i].style & WS_MINIMIZE) && IsCriticalPointOnDesktop(&winstate[i].rc)) {
|
|
wsprintf(szT, GetResString(IDS_LOCKWINDOW), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_LOCK_REAL, szT);
|
|
Count++;
|
|
}
|
|
wsprintf(szT, GetResString(IDS_CLOSE), winstate[i].szTitle);
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_DESTROY_REAL, szT);
|
|
Count++;
|
|
}
|
|
return(Count);
|
|
}
|
|
|
|
|
|
|
|
VOID DoPopupMenu(
|
|
PPOINT pptMouse,
|
|
PPOINT pptReal)
|
|
{
|
|
HMENU hMenu;
|
|
UINT wType, wTypeGhost;
|
|
RECT rc;
|
|
UINT Count = 0;
|
|
BOOL fFirst = TRUE;
|
|
|
|
hMenu = CreatePopupMenu();
|
|
|
|
ClientToScreen(hwndTopdesk, pptMouse);
|
|
pptMouse->y -= GetSystemMetrics(SM_CYMENU) / 2;
|
|
PopupPt = *pptReal;
|
|
|
|
PopuphwndFocus = MyWindowFromPt(pptReal, &wTypeGhost, &rc, &PopupGhostIndex,
|
|
FALSE);
|
|
if (wTypeGhost == HTY_GHOST) {
|
|
/*
|
|
* Allow popup menus to see through ghosts - real actions have
|
|
* priority over ghost actions.
|
|
*/
|
|
PopuphwndFocus = MyWindowFromPt(pptReal, &wType, &rc, &PopupRealIndex,
|
|
TRUE);
|
|
Count += AppendPopupMenuItems(hMenu, wType, PopupRealIndex, fFirst);
|
|
fFirst = FALSE;
|
|
} else {
|
|
PopupRealIndex = PopupGhostIndex;
|
|
wType = wTypeGhost;
|
|
}
|
|
Count += AppendPopupMenuItems(hMenu, wTypeGhost, PopupGhostIndex, fFirst);
|
|
|
|
if (!PtInRect(&rcrDT, *pptReal)) {
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_JUMP_DESKTOP, GetResString(IDS_JUMPTOTHISDESKTOP));
|
|
Count++;
|
|
}
|
|
if (pro.fRelative) {
|
|
SetRect(&rc, oxrHDT, oyrHDT, oxrHDT + cxrDT, oyrHDT + cyrDT);
|
|
} else {
|
|
SetRect(&rc, -oxrCDT, -oyrCDT, -oxrCDT + cxrDT, -oyrCDT + cyrDT);
|
|
}
|
|
if (!PtInRect(&rc, *pptReal)) {
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMDP_SETHOME, GetResString(IDS_MAKETHISHOME));
|
|
Count++;
|
|
}
|
|
|
|
if (!pro.fShowFrameCtrls) {
|
|
if (Count) {
|
|
AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
|
|
}
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMD_CONFIG, GetResString(IDS_OPTIONS));
|
|
Count++;
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMD_DISTRIBUTE, GetResString(IDS_MOVEWINDOWSTOGHOSTS));
|
|
Count++;
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMD_SNAPSHOT, GetResString(IDS_CREATEGHOSTS));
|
|
Count++;
|
|
if (cGhosts) {
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMD_ERASEGHOSTS, GetResString(IDS_DELETEGHOSTS));
|
|
Count++;
|
|
}
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMD_TOGGLE_GHOSTS, GetResString(IDS_TOGGLEGHOSTS));
|
|
Count++;
|
|
AppendMenu(hMenu, MF_SEPARATOR, 0, 0);
|
|
Count++;
|
|
AppendMenu(hMenu, MF_ENABLED | MF_STRING | MF_UNCHECKED,
|
|
CMD_HELP, GetResString(IDS_HELP));
|
|
Count++;
|
|
}
|
|
|
|
|
|
if (Count) {
|
|
TrackPopupMenu(hMenu, TPM_CENTERALIGN | TPM_RIGHTBUTTON,
|
|
pptMouse->x, pptMouse->y, 0, hwndTopdesk, NULL);
|
|
}
|
|
|
|
DestroyMenu(hMenu);
|
|
}
|
|
|
|
|
|
|
|
|
|
/********** TopDesk Window Procedure **************/
|
|
|
|
LONG APIENTRY TopDeskWndProc(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
INT iReal;
|
|
RECT rc;
|
|
HMENU hMenu;
|
|
HWND hwndTop;
|
|
|
|
if (msg == wmRefreshMsg) {
|
|
MSG msg;
|
|
|
|
while (PeekMessage(&msg, hwnd, wmRefreshMsg, wmRefreshMsg, PM_REMOVE)) {
|
|
if (msg.lParam) {
|
|
lParam = msg.lParam;
|
|
wParam = msg.wParam; // grab the most recent event
|
|
}
|
|
}
|
|
RefreshWinState();
|
|
|
|
/*
|
|
* Hack to make Alt-Tab work on CMD windows:
|
|
*
|
|
* Cmd windows can't be hooked so we can't know when they get
|
|
* focus. This check causes the desktop to jerk to whoever has
|
|
* the focus if its not us and the window is not on the current
|
|
* desktop.
|
|
*/
|
|
hwndTop = GetForegroundWindow();
|
|
if (!fStartingGhost && hwndTop != NULL && hwndTop != hwndTopdesk) {
|
|
GetWindowRect(hwndTop, &rc);
|
|
if (!IsCriticalPointOnDesktop(&rc)) {
|
|
lParam = TRUE;
|
|
wParam = (WPARAM)hwndTop;
|
|
}
|
|
}
|
|
|
|
if (lParam) { // fJerkDesktop
|
|
for (iReal = 0; iReal < cWindows; iReal++) {
|
|
if (winstate[iReal].hwnd == (HWND)wParam) {
|
|
int x, y;
|
|
|
|
GetBestGuessRect(&rc, &winstate[iReal]);
|
|
GetCriticalPoint(&rc, &x, &y);
|
|
JerkDesktop(x, y, NULL, iReal);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
switch (msg) {
|
|
case WM_NCCREATE:
|
|
return(ibDefWindowProc(hwnd, msg, wParam, lParam));
|
|
|
|
case WM_CREATE:
|
|
|
|
hwndTopdesk = hwnd;
|
|
|
|
hMenu = GetSystemMenu( hwndTopdesk, FALSE );
|
|
AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
|
|
AppendMenu( hMenu, MF_ENABLED | MF_CHECKED | MF_STRING, CMD_TOPMOST,
|
|
pszTopmost );
|
|
AppendMenu(GetSystemMenu(hwndTopdesk, FALSE),
|
|
MF_ENABLED | MF_STRING, CMD_TOGGLE_FRM_CTRLS,
|
|
pszShowFrmCtrls );
|
|
SetWindowPos(hwndTopdesk,
|
|
pro.fAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0,
|
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
if (!pro.fShowFrameCtrls) {
|
|
INT mfT ;
|
|
|
|
mfT = pro.mfx; // swap these so that when frame controls
|
|
pro.mfx = pro.mfxAlt; // are changed we revert back to what we
|
|
pro.mfxAlt = mfT; // last had before recalcing.
|
|
|
|
mfT = pro.mfy;
|
|
pro.mfy = pro.mfyAlt;
|
|
pro.mfyAlt = mfT;
|
|
|
|
pro.fShowFrameCtrls = TRUE;
|
|
PostMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(CMD_TOGGLE_FRM_CTRLS, 0, 0));
|
|
}
|
|
return(FALSE);
|
|
break;
|
|
|
|
case WM_HOTKEY:
|
|
if (hwndTopdesk == GetForegroundWindow()) {
|
|
HWND hwndTop = GetTopAppHwnd();
|
|
#ifdef WIN16
|
|
SetActiveWindow(hwndTop);
|
|
#else // WIN32
|
|
SetForegroundWindow(hwndTop);
|
|
#endif // WIN16
|
|
} else {
|
|
#ifdef WIN16
|
|
SetActiveWindow(hwndTopdesk);
|
|
#else // WIN32
|
|
SetForegroundWindow(hwndTopdesk);
|
|
#endif // WIN16
|
|
if (IsIconic(hwndTopdesk)) {
|
|
ShowWindow(hwndTopdesk, SW_RESTORE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_ENDSESSION:
|
|
case WM_CLOSE:
|
|
/*
|
|
* Hack for Johnsp - don't gather if shift-key is down.
|
|
*/
|
|
if (!(GetKeyState(VK_SHIFT) & 0x8000)) {
|
|
GatherWindows();
|
|
}
|
|
SaveProfile();
|
|
FreeStartupInfo();
|
|
#ifdef WIN32
|
|
UnregisterHotKey(hwndTopdesk, 1);
|
|
#endif
|
|
DestroyWindow(hwndTopdesk);
|
|
DeleteBrushes();
|
|
SelectObject(hdcMem, hbmOldMem);
|
|
DeleteObject(hbmMem);
|
|
DeleteDC(hdcMem);
|
|
DeleteObject(hMyFont);
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
DeleteBrushes();
|
|
CreateBrushes();
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
return(1); // we handle this in the paint processing.
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
PostMessage(hwnd, wmRefreshMsg, 0, 0);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rc;
|
|
|
|
GetClientRect(hwndTopdesk, &rc);
|
|
BeginPaint(hwnd, &ps);
|
|
TopDeskPaint(hdcMem, rc);
|
|
BitBlt(ps.hdc, rc.left, rc.top,
|
|
rc.right - rc.left,
|
|
rc.bottom - rc.top,
|
|
hdcMem, rc.left, rc.top, SRCCOPY);
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
break;
|
|
|
|
case WM_INITMENU:
|
|
case WM_INITMENUPOPUP:
|
|
// CMD_TOPMOST
|
|
CheckMenuItem((HMENU)wParam, CMD_TOPMOST,
|
|
pro.fAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
// CMD_MAGNIFY
|
|
EnableMenuItem((HMENU)wParam, CMD_MAGNIFY,
|
|
(pro.mfx > 0 || pro.mfy > 0) ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_REDUCE
|
|
EnableMenuItem((HMENU)wParam, CMD_REDUCE,
|
|
(cxcDT > cxcDTmin || cycDT > cycDTmin) ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_GOHOME
|
|
EnableMenuItem((HMENU)wParam, CMD_GOHOME,
|
|
(oxrHDT != oxrCDT || oyrHDT != oyrCDT) ?
|
|
MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_SETHOME
|
|
EnableMenuItem((HMENU)wParam, CMD_SETHOME,
|
|
(oxrHDT != oxrCDT || oyrHDT != oyrCDT) ?
|
|
MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_RELAVIVE_VIEW
|
|
CheckMenuItem((HMENU)wParam, CMD_RELATIVE_VIEW, pro.fRelative ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
// CMD_ABSOLUTE_VIEW
|
|
CheckMenuItem((HMENU)wParam, CMD_ABSOLUTE_VIEW, pro.fRelative ? MF_UNCHECKED : MF_CHECKED);
|
|
|
|
// CMD_TOGGLE_FRM_CTRLS
|
|
CheckMenuItem((HMENU)wParam, CMD_TOGGLE_FRM_CTRLS, pro.fShowFrameCtrls ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
// CMD_CONFIG
|
|
// CMD_EXIT
|
|
// CMD_DISTRIBUTE
|
|
EnableMenuItem((HMENU)wParam, CMD_DISTRIBUTE,
|
|
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_GATHER
|
|
// CMD_HIDE_GHOSTS
|
|
EnableMenuItem((HMENU)wParam, CMD_HIDE_GHOSTS,
|
|
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
CheckMenuItem((HMENU)wParam,
|
|
CMD_HIDE_GHOSTS, pro.iShowGhosts == SG_NONE ?
|
|
MF_CHECKED : MF_UNCHECKED);
|
|
|
|
// CMD_PARTIAL_GHOSTS
|
|
EnableMenuItem((HMENU)wParam, CMD_PARTIAL_GHOSTS,
|
|
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
CheckMenuItem((HMENU)wParam,
|
|
CMD_PARTIAL_GHOSTS, pro.iShowGhosts == SG_PARTIAL ?
|
|
MF_CHECKED : MF_UNCHECKED);
|
|
|
|
// CMD_SHOW_GHOSTS
|
|
EnableMenuItem((HMENU)wParam, CMD_SHOW_GHOSTS,
|
|
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
CheckMenuItem((HMENU)wParam,
|
|
CMD_SHOW_GHOSTS, pro.iShowGhosts == SG_ALL ?
|
|
MF_CHECKED : MF_UNCHECKED);
|
|
|
|
// CMD_SNAPSHOT
|
|
// CMD_ERASEGHOSTS
|
|
EnableMenuItem((HMENU)wParam, CMD_ERASEGHOSTS,
|
|
cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_STARTUPINFO
|
|
EnableMenuItem((HMENU)wParam, CMD_STARTUPINFO,
|
|
(pStartupInfo != NULL) && cGhosts ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
|
|
|
// CMD_HELP
|
|
// CMD_ABOUT
|
|
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
TrackWindow(LOWORD(lParam), HIWORD(lParam));
|
|
InvalidateRect(hwndTopdesk, NULL, TRUE);
|
|
return(CondDefWindowProc(hwnd, msg, wParam, lParam));
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
{
|
|
UINT wType;
|
|
RECT rc;
|
|
POINT pt;
|
|
INT i;
|
|
DWORD time;
|
|
BOOL fSkipMenu;
|
|
MSG msgS;
|
|
|
|
pt.x = xc2xr(LOWORD(lParam));
|
|
pt.y = yc2yr(HIWORD(lParam));
|
|
time = GetTickCount();
|
|
fSkipMenu = FALSE;
|
|
while (GetTickCount() < time + DEBOUNCE_TIMEOUT) {
|
|
if (PeekMessage(&msgS, hwnd, WM_RBUTTONUP, WM_RBUTTONUP,
|
|
PM_NOREMOVE)) {
|
|
fSkipMenu = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (fSkipMenu) {
|
|
hwndFocus = MyWindowFromPt(&pt, &wType, &rc, &i, FALSE);
|
|
if ((wType & HTY_REAL) && (hwndFocus != hwndTopdesk)) {
|
|
JerkDesktop(pt.x, pt.y, hwndFocus, i);
|
|
} else if (wType == HTY_NONE || wType & HTY_HOME) {
|
|
JerkDesktop(pt.x, pt.y, (HWND)0, -1);
|
|
} else if ((wType & HTY_GHOST)) {
|
|
StartGhostWindow(i);
|
|
}
|
|
} else {
|
|
POINT ptMouse;
|
|
|
|
ptMouse.x = LOWORD(lParam);
|
|
ptMouse.y = HIWORD(lParam);
|
|
DoPopupMenu(&ptMouse, &pt);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
CommandMsg(CMD_TOGGLE_FRM_CTRLS);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if (!CommandMsg(GET_WM_COMMAND_ID(wParam, lParam)))
|
|
goto DoDWP;
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
CommandMsg(GET_WM_COMMAND_ID(wParam, lParam));
|
|
goto DoDWP;
|
|
|
|
case WM_SIZE:
|
|
if (fStarted && !fFrameToggleSize && (wParam != SIZE_MINIMIZED)) {
|
|
cxc = LOWORD(lParam);
|
|
cyc = HIWORD(lParam);
|
|
CalcConversionFactors(TRUE);
|
|
pro.mfxAlt = pro.mfx;
|
|
pro.mfyAlt = pro.mfy;
|
|
}
|
|
fFrameToggleSize = FALSE;
|
|
RefreshWinState();
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
if (pro.fHideNoFocus && GetForegroundWindow() != hwndTopdesk) {
|
|
#ifdef HIDEIT
|
|
GetWindowRect(hwndTopdesk, &rc);
|
|
if (IntersectRect(&rc2, &rc, &rcrDT)) {
|
|
SetWindowPos(hwndTopdesk, NULL, rc.left + rcrDT.right,
|
|
rc.top + rcrDT.bottom, 0, 0,
|
|
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
|
|
}
|
|
#else
|
|
ShowWindow(hwndTopdesk, SW_SHOWMINNOACTIVE);
|
|
#endif // HIDEIT
|
|
}
|
|
goto DoDWP;
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
if (pro.fHideNoFocus) {
|
|
#ifdef HIDEIT
|
|
GetWindowRect(hwndTopdesk, &rc);
|
|
if (!IntersectRect(&rc2, &rc, &rcrDT)) {
|
|
SetWindowPos(hwndTopdesk, NULL, rc.left - rcrDT.right,
|
|
rc.top - rcrDT.bottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
#endif // HIDEIT
|
|
}
|
|
// fall through
|
|
|
|
case WM_MOVE:
|
|
if (fStarted) {
|
|
RefreshWinState();
|
|
}
|
|
// fall through
|
|
|
|
default:
|
|
DoDWP:
|
|
return(CondDefWindowProc(hwnd, msg, wParam, lParam));
|
|
break;
|
|
}
|
|
return(0L);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL InitApplication(
|
|
HANDLE hInst)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
InitResString(&pszTopmost, IDS_TOPMOST);
|
|
InitResString(&pszShowFrmCtrls, IDS_SHOWFRMCTRLS);
|
|
InitResString(&pszData, IDS_DATA);
|
|
InitResString(&pszTopdeskHelpTitle, IDS_TOPDESKHELPTITLE);
|
|
InitResString(&pszHelpFileName, IDS_HELPFILENAME);
|
|
InitResString(&pszWorking, IDS_WORKING);
|
|
InitResString(&pszProfile, IDS_PROFILE);
|
|
InitResString(&pszStartupInfo, IDS_STARTUPINFO);
|
|
InitResString(&pszTitle, IDS_TITLE);
|
|
InitSubstResString(&pszSubKey, IDS_SUBKEY, IDS_VERSION_NUM);
|
|
InitSubstResString(&pszVersion, IDS_VERSION, IDS_VERSION_NUM);
|
|
|
|
InitResString(&pszElementNames[SPACECOLOR], IDS_SPACECOLOR);
|
|
InitResString(&pszElementNames[WINDOWFILLCOLOR], IDS_WINDOWFILLCOLOR);
|
|
InitResString(&pszElementNames[WINDOWFRAMECOLOR], IDS_WINDOWFRAMECOLOR);
|
|
InitResString(&pszElementNames[DESKFRAMECOLOR], IDS_DESKFRAMECOLOR);
|
|
InitResString(&pszElementNames[GRIDCOLOR], IDS_GRIDCOLOR);
|
|
InitResString(&pszElementNames[GHOSTFRAMECOLOR], IDS_GHOSTFRAMECOLOR);
|
|
InitResString(&pszElementNames[WINDOWTEXT], IDS_WINDOWTEXT);
|
|
InitResString(&pszElementNames[FIXEDFRAMECOLOR], IDS_FIXEDFRAMECOLOR);
|
|
InitResString(&pszElementNames[GHOSTTEXTCOLOR], IDS_GHOSTTEXTCOLOR);
|
|
|
|
if (hwndTopdesk = FindWindow(pszTitle, pszTitle)) {
|
|
DPRINTF((hfDbgOut, "Found another TopDesk.\n"));
|
|
SendMessage(hwndTopdesk, WM_HOTKEY, 0, 0);
|
|
return(FALSE); // we are already running!
|
|
}
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_SAVEBITS | CS_DBLCLKS;
|
|
wc.lpfnWndProc = TopDeskWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInst;
|
|
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDR_ICON));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = NULL;
|
|
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
|
|
wc.lpszClassName = pszTitle;
|
|
|
|
if (RegisterClass(&wc)) {
|
|
return(TRUE);
|
|
} else {
|
|
DPRINTF((hfDbgOut, "RegisterClass failed!"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
BOOL InitSubstResString(
|
|
LPTSTR *ppsz,
|
|
DWORD id1,
|
|
DWORD id2)
|
|
{
|
|
LPTSTR pszT;
|
|
|
|
pszT = GetResString(id2);
|
|
_tcscpy(szResString2, pszT);
|
|
pszT = GetResString(id1);
|
|
*ppsz = LocalAlloc(LPTR, (_tcslen(pszT) + _tcslen(szResString2) + 1) * sizeof(TCHAR));
|
|
if (*ppsz != NULL) {
|
|
wsprintf(*ppsz, pszT, szResString2);
|
|
return(TRUE);
|
|
}
|
|
DPRINTF((hfDbgOut, "InitSubstResString(%d, %d) failed.\n", id1, id2));
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
BOOL InitResString(
|
|
LPTSTR *ppsz,
|
|
DWORD id)
|
|
{
|
|
LPTSTR pszT;
|
|
|
|
pszT = GetResString(id);
|
|
*ppsz = LocalAlloc(LPTR, (_tcslen(pszT) + 1) * sizeof(TCHAR));
|
|
if (*ppsz != NULL) {
|
|
_tcscpy(*ppsz, pszT);
|
|
return(TRUE);
|
|
}
|
|
DPRINTF((hfDbgOut, "InitResString(%d) failed.\n", id));
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
BOOL TopDeskInit()
|
|
{
|
|
HDC hdc;
|
|
int i;
|
|
OSVERSIONINFO ovi;
|
|
|
|
wmRefreshMsg = RegisterWindowMessage(TEXT(szMYWM_REFRESH));
|
|
if (RegOpenKey(HKEY_CURRENT_USER, pszSubKey, &hKeyTopDesk) != ERROR_SUCCESS) {
|
|
if (RegCreateKey(HKEY_CURRENT_USER, pszSubKey, &hKeyTopDesk) != ERROR_SUCCESS) {
|
|
DPRINTF((hfDbgOut, "Could not open registry key.\n"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
for (i = 0; i < MAX_ICOLOR; i++) {
|
|
pro.ahbr[i] = orgColors[i];
|
|
}
|
|
|
|
cxrDT = GetSystemMetrics(SM_CXSCREEN);
|
|
cyrDT = GetSystemMetrics(SM_CYSCREEN);
|
|
cxFrame = GetSystemMetrics(SM_CXFRAME);
|
|
cyFrame = GetSystemMetrics(SM_CYFRAME);
|
|
|
|
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&ovi);
|
|
fCairoShell = ovi.dwMajorVersion >= 4;
|
|
|
|
if (!GetProfile()) {
|
|
pro.x = 0;
|
|
pro.y = 0;
|
|
pro.cx = cxrDT / 4;
|
|
pro.cy = cyrDT / 3;
|
|
}
|
|
hMyFont = CreateFontIndirect(&pro.lf);
|
|
if (!hMyFont) {
|
|
DPRINTF((hfDbgOut, "Could not create font.\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
fpRefreshEnumProc = MakeProcInstance((FARPROC)RefreshEnumProc, hInst);
|
|
if (fpRefreshEnumProc == NULL) {
|
|
DPRINTF((hfDbgOut, "MakeProcInstance failied.\n"));
|
|
return(FALSE);
|
|
}
|
|
hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCEL));
|
|
if (!hAccel) {
|
|
DPRINTF((hfDbgOut, "Could not load accelerators.\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
SetRect(&rcrDT, 0, 0, cxrDT, cyrDT);
|
|
cxcDTmin = GetSystemMetrics(SM_CXICON) / 2;
|
|
cycDTmin = GetSystemMetrics(SM_CYICON) / 2;
|
|
hwndDT = GetDesktopWindow();
|
|
CreateBrushes();
|
|
hdc = GetDC(NULL);
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
hbmMem = CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES),
|
|
GetDeviceCaps(hdc, VERTRES));
|
|
hbmOldMem = SelectObject(hdcMem, hbmMem);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int WINAPI WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
|
|
lpCmdLine;
|
|
nCmdShow;
|
|
|
|
hInst = hInstance;
|
|
|
|
#ifdef DEBUG
|
|
hfDbgOut = fopen("topdesk.log", "w");
|
|
if (hfDbgOut == NULL) {
|
|
MessageBeep(0);
|
|
MessageBeep(0);
|
|
MessageBeep(0);
|
|
return(0);
|
|
}
|
|
#endif // DEBUG
|
|
if (!InitApplication(hInstance)) {
|
|
return (FALSE);
|
|
}
|
|
|
|
if (!TopDeskInit()) {
|
|
return(FALSE);
|
|
}
|
|
|
|
hwndTopdesk = CreateWindow(pszTitle, pszTitle,
|
|
WS_OVERLAPPED | WS_THICKFRAME | MD_FRAMESTYLES | IBS_HORZCAPTION,
|
|
0, 0, 0, 0, NULL, NULL, hInst, NULL);
|
|
if (!hwndTopdesk) {
|
|
DPRINTF((hfDbgOut, "CreateWindow failed.\n"));
|
|
return(0);
|
|
}
|
|
|
|
SetWindowLong(hwndTopdesk, GWL_STYLE,
|
|
GetWindowLong(hwndTopdesk, GWL_STYLE) | WS_DLGFRAME);
|
|
ibSetCaptionSize(hwndTopdesk, GetSystemMetrics(SM_CYCAPTION) / 2 + 1);
|
|
SetTimer(hwndTopdesk, 1, TIMEOUT_REFRESH, NULL);
|
|
MoveWindow(hwndTopdesk, pro.x, pro.y, pro.cx, pro.cy, TRUE);
|
|
ShowWindow(hwndTopdesk, SW_SHOW);
|
|
SetActiveWindow(hwndTopdesk);
|
|
fStarted = TRUE;
|
|
CommandMsg(CMD_GOHOME);
|
|
|
|
RegisterHotKey(hwndTopdesk, 1,
|
|
(pro.fShift ? MOD_SHIFT : 0) |
|
|
(pro.fControl ? MOD_CONTROL : 0) |
|
|
(pro.fAlt ? MOD_ALT : 0),
|
|
pro.vkey);
|
|
|
|
if (SetTopDeskHooks(hwndTopdesk)) {
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
if (IsIconic(hwndTopdesk) ||
|
|
!TranslateAccelerator(hwndTopdesk, hAccel, &msg)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
} else {
|
|
MessageBox(hwndTopdesk, GetResString(IDS_CANTSETHOOKS),
|
|
pszTitle, MB_OK);
|
|
DPRINTF((hfDbgOut, "Could not set hooks.\n"));
|
|
}
|
|
|
|
if (hKeyTopDesk) {
|
|
RegCloseKey(hKeyTopDesk);
|
|
}
|
|
FreeProcInstance(fpRefreshEnumProc);
|
|
#ifdef DEBUG
|
|
fclose(hfDbgOut);
|
|
#endif // DEBUG
|
|
return(0);
|
|
}
|
|
|