Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2161 lines
66 KiB

/*****************************************************************************
C L I P B O A R D
Name: clipbrk.c
Date: 21-Jan-1994
Creator: Unknown
Description:
This is the main clipbrd module. It has the program entry point,
the windows procedures and some major supporting functions.
*****************************************************************************/
#define WIN31
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <lm.h>
#include <nddeapi.h>
#include <nddeagnt.h>
#include <stdio.h>
#include <htmlhelp.h>
#include <strsafe.h>
#include "common.h"
#include "clipbook.h"
#include "clipbrd.h"
#include "dialogs.h"
#include "clipdsp.h"
#include "cvutil.h"
#include "cvinit.h"
#include "auditchk.h"
#include "callback.h"
#include "debugout.h"
#include "helpids.h"
#include "initmenu.h"
#include "cvcomman.h"
#include "clipfile.h"
#include "strtok.h"
#include "security.h"
#ifndef UNICODE_CHARSET
#define UNICODE_CHARSET 1
#endif
//
// return code of OnPaint
//
#define ONPAINT_FAIL 0
#define ONPAINT_SUCCESS 1
#define ONPAINT_NOCLIPBRD 2
typedef UINT (WINAPI *WNETCALL)(HWND, LPSTR, LPSTR, WORD, DWORD );
// Static data
static HHOOK hMsgFilterHook;
// Stuff for dealing with minimized MDI children
static HCURSOR hcurClipbook;
static HCURSOR hcurClipbrd;
static HCURSOR hcurRemote;
static BOOL fClpOpen;
HANDLE hmutexClp; // clipboard mutex
HANDLE hXacting; // transaction event
HANDLE hmodNetDriver;
HICON hicClipbrd;
HICON hicClipbook;
HICON hicRemote;
HICON hicLock; // Icon for Lock on thumbnail bitmaps
HFONT hfontUni; // Handle for Unicode font, if it exists
// Application-wide flags
BOOL fStatus; // status bar shown?
BOOL fToolBar; // tool bar shown?
BOOL fShareEnabled; // sharing allowed in system.ini?
BOOL fNetDDEActive = TRUE; // NetDDE detected?
BOOL fAppLockedState = FALSE; // app UI locked (see LockApp())
BOOL fClipboardNeedsPainting = FALSE; // indicates deferred clp paint
BOOL fSharePreference; // shared checked on paste?
BOOL fNeedToTileWindows = FALSE; // need to tile windows on size
BOOL fAppShuttingDown = FALSE; // in process of closing
BOOL fFillingClpFromDde = FALSE; // in process of adding clp formats
BOOL fAuditEnabled;
HWND hwndNextViewer = NULL; // for clpbrd viewer chain
HWND hwndDummy; // used as dummy SetCapture target
// special case clipboard formats
UINT cf_bitmap; // we send/receive these in private 'packed' format
UINT cf_metafilepict;
UINT cf_palette;
UINT cf_preview; // PREVBMPSIZxPREVBMPSIZ preview bitmap private format
// these are formats that contain untranslated copies of link and objlink data
UINT cf_objectlinkcopy;
UINT cf_objectlink;
UINT cf_linkcopy;
UINT cf_link;
// DDEML
// These are effective constants created once and destroyed when we die
HSZ hszSystem;
HSZ hszTopics;
HSZ hszDataSrv;
HSZ hszFormatList;
HSZ hszClpBookShare;
DWORD idInst = 0;
DWORD dwCurrentHelpId = 0L;
// instance proc from MSGF_DDEMGR filter
WINDOWPLACEMENT Wpl;
HOOKPROC lpMsgFilterProc;
HINSTANCE hInst;
HACCEL hAccel;
HFONT hOldFont;
HFONT hFontStatus;
HFONT hFontPreview;
HWND hwndActiveChild = 0; // this handle identifies the currently active MDI window
PMDIINFO pActiveMDI = NULL; // this pointer points to the MDI info struct of the
// active MDI window IT SHOULD ALWAYS ==
// GETMDIINFO(hwndActiveChild)
HWND hwndClpbrd = 0; // this handle identifies the clipboard window
HWND hwndLocal = 0; // this handle identifies the local clipbook window
HWND hwndClpOwner = 0; // this handle identifies the clipboard owning MDI child (if any)
HWND hwndMDIClient; // handle to MDI Client window
HWND hwndApp; // global app window
HDC hBtnDC; // memory DC used for owner draw stuff
HBITMAP hOldBitmap;
HBITMAP hPreviewBmp;
HBITMAP hPgUpBmp;
HBITMAP hPgDnBmp;
HBITMAP hPgUpDBmp;
HBITMAP hPgDnDBmp;
int dyStatus; // height of status bar
int dyButtonBar; // height of button bar
int dyPrevFont; // height of listbox font - height+external
TCHAR szHelpFile[] = TEXT("clipbrd.hlp");
TCHAR szChmHelpFile[] = TEXT("clipbrd.chm");
TCHAR szClipBookClass[] = TEXT("ClipBookWClass"); // frame window class
TCHAR szChild[] = TEXT("CVchild"); // Class name for MDI window
TCHAR szDummy[] = TEXT("CVdummy"); // class name of hidden dummy window
TCHAR szNDDEcode[] = TEXT("NDDE$");
TCHAR szNDDEcode1[] = TEXT("NDDE$0001");
TCHAR szClpBookShare[] = TEXT("CLPBK$");
// localized strings
TCHAR szHelv[SMLRCBUF]; // status line font
TCHAR szAppName[SMLRCBUF];
TCHAR szLocalClpBk[SMLRCBUF];
TCHAR szSysClpBrd[SMLRCBUF];
TCHAR szDataUnavail[BIGRCBUF];
TCHAR szReadingItem[BIGRCBUF];
TCHAR szViewHelpFmt[BIGRCBUF];
TCHAR szActivateFmt[BIGRCBUF];
TCHAR szRendering[BIGRCBUF];
TCHAR szDefaultFormat[BIGRCBUF];
TCHAR szGettingData[BIGRCBUF];
TCHAR szEstablishingConn[BIGRCBUF];
TCHAR szClipBookOnFmt[BIGRCBUF];
TCHAR szPageFmt[SMLRCBUF];
TCHAR szPageFmtPl[SMLRCBUF];
TCHAR szPageOfPageFmt[SMLRCBUF];
TCHAR szDelete[SMLRCBUF];
TCHAR szDeleteConfirmFmt[SMLRCBUF];
TCHAR szFileFilter[BIGRCBUF];
TCHAR *szFilter;
// Registry key strings
TCHAR szRoot[128];
TCHAR szPref[] = TEXT("Preferences");
TCHAR szConn[] = TEXT("Connections");
TCHAR szStatusbar[] = TEXT("StatusBar");
TCHAR szToolbar[] = TEXT("ToolBar");
TCHAR szShPref[] = TEXT("AutoShare");
TCHAR szEnableShr[] = TEXT("EnableShare");
TCHAR szDefView[] = TEXT("DefView");
#if DEBUG
TCHAR szDebug[] = TEXT("Debug");
#endif
TCHAR szNull[] = TEXT("");
HKEY hkeyRoot;
TCHAR szBuf[SZBUFSIZ];
TCHAR szBuf2[SZBUFSIZ];
TCHAR szConvPartner[128]; // bigger than max server name
TCHAR szKeepAs[ MAX_NDDESHARENAME + 2 ];
static BOOL InitApplication (HINSTANCE hInstance);
static BOOL InitInstance (HINSTANCE hInstance, int nCmdShow);
static VOID StripCharRange (TCHAR *s, char lower, char upper);
static VOID SendMessageToKids (WORD msg, WPARAM wParam, LPARAM lParam);
static VOID StripAcceleratorKey (TCHAR *s);
////////////////////// functions //////////////////////////////////
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
OFSTRUCT of;
PMDIINFO pMDI;
#if DEBUG
DebugLevel = 2;
#endif
LoadString(hInstance, IDS_APPNAME, szAppName, SMLRCBUF);
// Only one instance is supported
// hPrevInstance always == null under NT, so we have to rely on FWin.
if (hwndApp = FindWindow(szClipBookClass, NULL))
{
PINFO(TEXT("Found previous instance\r\n"));
if (IsIconic(hwndApp))
{
ShowWindow(hwndApp, SW_RESTORE);
SetForegroundWindow(hwndApp);
}
else
{
SetForegroundWindow(hwndApp);
}
return FALSE;
}
if (!InitApplication(hInstance))
{
PERROR(TEXT("InitApp fail\r\n"));
return (FALSE);
}
if (!InitInstance(hInstance, nCmdShow ))
{
PERROR(TEXT("InitInstance fail\r\n"));
return (FALSE);
}
UpdateWindow ( hwndApp );
// if we were started with the name of a file on the command line,
// attempt to load the .clp file via an open dde execute
if (OpenFile (lpCmdLine, &of, OF_EXIST) != HFILE_ERROR )
{
if ( ClearClipboard(hwndApp) )
{
#ifdef UNICODE
TCHAR *ptch;
ptch = (TCHAR *)LocalAlloc (LPTR, (lstrlenA(lpCmdLine) + 1) * sizeof(TCHAR));
MultiByteToWideChar (CP_ACP,
MB_PRECOMPOSED,
lpCmdLine,
-1,
ptch,
lstrlenA(lpCmdLine)+1);
lstrcat(lstrcpy(szBuf, SZCMD_OPEN),ptch);
#else
StringCchCopy(szBuf, SZBUFSIZ, SZCMD_OPEN),
StringCchCat (szBuf, SZBUFSIZ, lpCmdLine);
#endif
if (pMDI = GETMDIINFO(hwndLocal))
{
MySyncXact ((LPBYTE)szBuf,
lstrlen(szBuf) +1,
pMDI->hExeConv,
0L,
CF_TEXT,
XTYP_EXECUTE,
SHORT_SYNC_TIMEOUT,
NULL );
}
InitializeMenu ( GetMenu(hwndApp) );
}
}
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateMDISysAccel (hwndMDIClient, &msg) &&
(hAccel? !TranslateAccelerator(hwndApp, hAccel, &msg): 1))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// Clear the mutex
CloseHandle(hmutexClp);
// free up our HSZ 'constants'
DdeFreeStringHandle(idInst, hszTopics);
DdeFreeStringHandle(idInst, hszFormatList );
DdeFreeStringHandle(idInst, hszSystem);
DdeFreeStringHandle(idInst, hszDataSrv);
DdeFreeStringHandle(idInst, hszClpBookShare );
DdeFreeStringHandle(idInst, hszErrorRequest);
// Free icons & cursors
DestroyIcon(hicClipbrd);
DestroyIcon(hicClipbook);
DestroyIcon(hicRemote);
DestroyIcon(hicLock);
DestroyCursor(hcurClipbrd);
DestroyCursor(hcurClipbook);
DestroyCursor(hcurRemote);
DdeUninitialize(idInst);
UnhookWindowsHookEx(hMsgFilterHook);
return (int)(msg.wParam);
}
static BOOL InitApplication (HINSTANCE hInstance)
{
WNDCLASS wc;
// Register the frame window
wc.style = 0;
wc.lpfnWndProc = FrameWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon ( hInstance, MAKEINTRESOURCE(IDFRAMEICON) );
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL; // will paint whole client area
wc.lpszMenuName = MAKEINTRESOURCE(IDCVMENU);
wc.lpszClassName = szClipBookClass;
if (0 == RegisterClass(&wc))
{
return FALSE;
}
// Register the MDI child class
wc.lpfnWndProc = ChildWndProc;
wc.hIcon = NULL;
wc.lpszMenuName = NULL;
wc.cbWndExtra = CBWNDEXTRA;
wc.lpszClassName = szChild;
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
wc.style = CS_DBLCLKS;
if (0 == RegisterClass(&wc))
return FALSE;
// register dummy window for SetCapture target
wc.lpfnWndProc = DefWindowProc;
wc.hIcon = NULL;
wc.lpszMenuName = NULL;
wc.cbWndExtra = 0;
wc.lpszClassName = szDummy;
wc.style = 0;
if (0 == RegisterClass(&wc))
return FALSE;
return TRUE;
}
/*
* SetupForFloatingProfile
*/
static void SetupForFloatingProfile ()
{
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+3] = TEXT("\\\\");
DWORD cbName = sizeof(szComputerName) + 1;
NDDESHAREINFO ShareInfo =
{
1, // revision
szClpBookShare,
SHARE_TYPE_STATIC,
TEXT("ClipSrv|System\0\0"),
TRUE, // shared
TRUE, // a service
FALSE, // cannot be started
SW_SHOWNORMAL,
{0,0}, // mod id
0, // no item list
TEXT("")
};
START_NETDDE_SERVICES(hwndApp);
GetComputerName (&szComputerName[2], &cbName);
NDdeShareAdd (szComputerName,
2,
NULL,
(LPBYTE)&ShareInfo,
sizeof (ShareInfo));
NDdeSetTrustedShare (szComputerName,
szClpBookShare,
NDDE_TRUST_SHARE_START |
NDDE_TRUST_SHARE_INIT);
}
BOOL InitInstance(
HINSTANCE hInstance,
int nCmdShow)
{
LOGFONT UniFont;
DWORD dwKeyStatus;
HMENU hFileMenu;
SC_HANDLE hsc;
SC_HANDLE hsrvWksta;
SERVICE_STATUS ss;
UINT ddeErr;
// Stuff used to make the local server's name, "\\<computername>\NDDE$"
TCHAR atchSrvName[MAX_COMPUTERNAME_LENGTH + 9];
DWORD dwSize;
static TCHAR szBuffer[256] = TEXT("\0");
int cch, i;
LCID lcid = GetThreadLocale();
hInst = hInstance;
hmutexClp = CreateMutex(NULL, FALSE, SZMUTEXCLP);
hXacting = CreateEvent (NULL, FALSE, TRUE, NULL);
hAccel = LoadAccelerators(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDACCELERATORS));
if (NULL == hAccel)
{
PERROR(TEXT("error loading accelerator table\n\r"));
#ifndef DEBUG
return FALSE;
#endif
}
// Load cursors for dragging MDI children
hcurClipbook = LoadCursor (hInst, (LPCTSTR)MAKEINTRESOURCE(IDC_CLIPBOOK));
hcurClipbrd = LoadCursor (hInst, (LPCTSTR)MAKEINTRESOURCE(IDC_CLIPBRD));
hcurRemote = LoadCursor (hInst, (LPCTSTR)MAKEINTRESOURCE(IDC_REMOTE));
// Load icons for MDI children
hicClipbook = LoadIcon (hInst, (LPCTSTR)MAKEINTRESOURCE(IDI_CLIPBOOK));
hicClipbrd = LoadIcon (hInst, (LPCTSTR)MAKEINTRESOURCE(IDI_CLIPBRD));
hicRemote = LoadIcon (hInst, (LPCTSTR)MAKEINTRESOURCE(IDI_REMOTE));
// Load Lock icon
hicLock = LoadIcon ( hInst, MAKEINTRESOURCE(IDLOCKICON));
// Load the Unicode font, for displaying Unicode text.
GetObject (GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), (LPBYTE)&UniFont);
if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE ||
PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE ||
PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_KOREAN)
{
UniFont.lfCharSet = ANSI_CHARSET;
StringCchCopy(UniFont.lfFaceName, LF_FACESIZE, TEXT("Lucida Sans Unicode"));
}
else
{
UniFont.lfCharSet = UNICODE_CHARSET;
StringCchCopy(UniFont.lfFaceName, LF_FACESIZE, TEXT("Lucida Sans Unicode Regular"));
}
hfontUni = CreateFontIndirect(&UniFont);
if (hfontUni == NULL)
{
hfontUni = (HFONT)GetStockObject(SYSTEM_FONT);
}
LoadIntlStrings();
if(!szBuffer[0])
{
cch = LoadString( hInst, IDS_FILTERTEXT, szBuffer, sizeof(szBuffer) );
for( i = 0; i <= cch; i++ )
{
szBuffer[i] = (szBuffer[i] == TEXT('\1')) ? TEXT('\0') : szBuffer[i];
}
szFilter = szBuffer;
}
// initialize variables in clipdsp.c
fOwnerDisplay = FALSE;
// initialize DDEML
ddeErr = DdeInitialize (&idInst,(PFNCALLBACK)DdeCallback,APPCLASS_STANDARD, 0L);
if (DMLERR_NO_ERROR != ddeErr)
{
PERROR(TEXT("The DDEML did not initialize\n\r"));
DdeMessageBox (hInst, NULL, ddeErr, IDS_APPNAME, MB_OK|MB_ICONSTOP);
return FALSE;
}
// create our hsz constants
atchSrvName[0] = atchSrvName[1] = TEXT('\\');
dwSize = MAX_COMPUTERNAME_LENGTH+1;
GetComputerName(atchSrvName + 2, &dwSize);
StringCchCat(atchSrvName, MAX_COMPUTERNAME_LENGTH + 9, TEXT("\\NDDE$"));
hszDataSrv = DdeCreateStringHandleA(idInst, atchSrvName, CP_WINANSI);
hszSystem = DdeCreateStringHandleA(idInst, "CLPBK$", CP_WINANSI);
hszTopics = DdeCreateStringHandleA(idInst, SZDDESYS_ITEM_TOPICS, CP_WINANSI);
hszFormatList = DdeCreateStringHandleA(idInst, SZ_FORMAT_LIST, CP_WINANSI);
hszClpBookShare = DdeCreateStringHandleA(idInst, szClpBookShare, CP_WINANSI);
hszErrorRequest = DdeCreateStringHandleA(idInst, SZ_ERR_REQUEST, CP_WINANSI);
if (DdeGetLastError(idInst) != DMLERR_NO_ERROR )
{
PERROR(TEXT("DDEML error during init\n\r"));
return FALSE;
}
// We set this hook up so that we can catch the MSGF_DDEMGR message
// which is called when DDEML is in a modal loop during synchronous
// transaction processing.
lpMsgFilterProc = (HOOKPROC)MyMsgFilterProc;
hMsgFilterHook = SetWindowsHookEx (WH_MSGFILTER,
lpMsgFilterProc,
hInst,
GetCurrentThreadId());
if (NULL == hMsgFilterHook)
{
PERROR(TEXT("SetWindowsHook failed\n\r"));
return FALSE;
}
// get preference flags
LoadString(hInst, IDS_CLPBKKEY, szRoot, sizeof(szRoot));
if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_CURRENT_USER,
szRoot,
0L,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE |
KEY_SET_VALUE |
KEY_ENUMERATE_SUB_KEYS,
NULL,
&hkeyRoot,
&dwKeyStatus))
{
PERROR(TEXT("Could not set up root key\r\n"));
fStatus = TRUE;
fToolBar = TRUE;
fSharePreference = TRUE;
fShareEnabled = FALSE;
}
else
{
DWORD iSize = sizeof(fStatus);
PINFO (TEXT("Root key created. Key Status %ld."),dwKeyStatus);
if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szStatusbar,
NULL, NULL, (LPBYTE)&fStatus, &iSize))
{
fStatus = TRUE;
}
iSize = sizeof(fToolBar);
if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szToolbar,
NULL, NULL, (LPBYTE)&fToolBar, &iSize))
{
fToolBar = TRUE;
}
iSize = sizeof(fSharePreference);
if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szShPref,
NULL, NULL, (LPBYTE)&fSharePreference, &iSize))
{
fSharePreference = FALSE;
}
#if DEBUG
iSize = sizeof(DebugLevel);
if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szDebug, NULL, NULL,
(LPBYTE)&DebugLevel, &iSize))
{
DebugLevel = 2;
}
#endif
iSize = sizeof(fShareEnabled);
if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szEnableShr,
NULL, NULL, (LPBYTE)&fShareEnabled, &iSize))
{
fShareEnabled = TRUE;
}
}
// Figure out if NetBIOS is active or not, thus if we can net connect
fNetDDEActive = FALSE;
hsc = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (NULL != hsc)
{
hsrvWksta = OpenService(hsc, "LanmanWorkstation", SERVICE_QUERY_STATUS);
if (NULL != hsrvWksta)
{
if (QueryServiceStatus(hsrvWksta, &ss))
{
if (ss.dwCurrentState == SERVICE_RUNNING)
{
fNetDDEActive = TRUE;
}
}
CloseServiceHandle(hsrvWksta);
}
CloseServiceHandle(hsc);
}
else
{
PERROR(TEXT("Couldn't open SC mgr\r\n"));
}
// override if not on a domain
{
LPWSTR pszDomain;
NETSETUP_JOIN_STATUS nsjs;
if (NERR_Success == NetGetJoinInformation(NULL, &pszDomain, &nsjs))
{
if ( nsjs != NetSetupDomainName)
fNetDDEActive = FALSE;
NetApiBufferFree(pszDomain);
}
}
fAuditEnabled = AuditPrivilege(AUDIT_PRIVILEGE_CHECK);
// Create main window
if ( !( hwndApp = CreateWindow (szClipBookClass,
szAppName,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL)))
{
PERROR(TEXT("CreateWindow failed!\r\n"));
return FALSE;
}
SetupForFloatingProfile ();
// Get the handle to the Display popup menu for adding format entries
hDispMenu = GetSubMenu( GetMenu(hwndApp), DISPLAY_MENU_INDEX);
hFileMenu = GetSubMenu(GetMenu(hwndApp), 0);
// get rid of share menu entries?
if ( !fShareEnabled )
{
EnableMenuItem ( hFileMenu, IDM_SHARE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem ( hFileMenu, IDM_UNSHARE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem ( hFileMenu, IDM_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
}
// get rid of connect/disonnect entries?
if ( !fNetDDEActive )
{
EnableMenuItem ( hFileMenu, IDM_CONNECT, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem ( hFileMenu, IDM_DISCONNECT, MF_BYCOMMAND | MF_GRAYED);
}
DrawMenuBar(hwndApp);
if ( ReadWindowPlacement ( szAppName, &Wpl ))
{
Wpl.showCmd = nCmdShow;
Wpl.ptMaxPosition.x = -1;
Wpl.ptMaxPosition.y = -1;
SetWindowPlacement ( hwndApp, &Wpl );
UpdateWindow(hwndApp);
}
else
{
ShowWindow ( hwndApp, nCmdShow );
}
// make our SetCapture target window
if ( !( hwndDummy = CreateWindow (szDummy,
szNull,
WS_CHILD & ~WS_VISIBLE,
0,
0,
0,
0,
hwndApp,
NULL,
hInstance,
NULL )))
return FALSE;
// Make clipboard window -- needs to happen BEFORE we SetClipboardViewer,
// because hwndApp will get a WM_DRAWCLIPBOARD and there won't be any windows.
SendMessage ( hwndApp, WM_COMMAND, IDM_CLPWND, 0L );
// Attach us to the clipboard viewer chain
hwndNextViewer = SetClipboardViewer(hwndApp);
// create initial local window.
SendMessage ( hwndApp, WM_COMMAND, IDM_LOCAL, 0L );
// force paint before restoring other connections so we don't
// have to wait too long.
UpdateWindow(hwndApp);
// restore previous connections
if ( fNetDDEActive )
RestoreAllSavedConnections();
return TRUE;
}
// Strip all chars between lower and upper from string s, in place.
VOID StripCharRange (
TCHAR *s,
char lower,
char upper)
{
TCHAR *p = s, *q = s;
while( *p ){
if (IsDBCSLeadByte(*p)) {
*q++ = *p++;
*q++ = *p++;
}
else {
if (*p < lower || *p > upper) *q++ = *p++;
else
p++;
}
}
*q = TEXT('\0');
}
// Strip all occurrences of "(&)" from string s, in place
// Localized FE build uses "Bitmap(&B)" instead of "&Bitmap" in menu string.
VOID StripAcceleratorKey (
TCHAR *s)
{
TCHAR *p = s, *q = s;
while( *p ) {
#ifndef UNICODE
if (IsDBCSLeadByte(*p)) {
*q++ = *p++;
*q++ = *p++;
}
else
{
if ( (*p==TEXT('(')) && (*(p+1)==TEXT('&')) && (*(p+3)==TEXT(')')) )
p += 4;
else *q++ = *p++;
}
#else
if ( (*p==TEXT('(')) && (*(p+1)==TEXT('&')) && (*(p+3)==TEXT(')')) )
p += 4;
else *q++ = *p++;
#endif
}
*q = TEXT('\0');
}
/////////////////////////////////////////////////////////////////////////////
//
// Purpose: Message handler for WM_DRAWCLIPBOARD
//
// Params:
// hwnd - Window handle
/////////////////////////////////////////////////////////////////////////////
void OnDrawClipboard(
HWND hwnd)
{
UINT wNewFormat;
UINT wOldFormat;
HCURSOR hCursor;
// If we are in a transaction, defer processing this message
// until the next unlock - if we did this now we could cause
// other apps to break...
// clipboard may have been empty and now isn't
InitializeMenu ( GetMenu(hwnd) );
if (fAppLockedState)
{
fClipboardNeedsPainting = TRUE;
}
else
{
fClipboardNeedsPainting = FALSE;
hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
if (IsWindow ( hwndClpbrd ))
{
wOldFormat = GetBestFormat (hwndClpbrd,
GETMDIINFO(hwndClpbrd)->CurSelFormat );
GETMDIINFO(hwndClpbrd)->CurSelFormat = CBM_AUTO;
GETMDIINFO(hwndClpbrd)->fDisplayFormatChanged = TRUE;
wNewFormat = GetBestFormat( hwndClpbrd, CBM_AUTO );
// NOTE OwnerDisplay stuff applies only to the "real" clipboard!
ShowHideControls(hwndClpbrd);
if (wOldFormat == CF_OWNERDISPLAY)
{
/* Save the owner Display Scroll info */
SaveOwnerScrollInfo(hwndClpbrd);
ShowScrollBar ( hwndClpbrd, SB_BOTH, FALSE );
ResetScrollInfo( hwndClpbrd );
InvalidateRect ( hwndClpbrd, NULL, TRUE );
}
else
{
if (wNewFormat == CF_OWNERDISPLAY)
{
/* Restore the owner display scroll info */
ShowHideControls(hwndClpbrd);
ShowWindow ( pActiveMDI->hwndSizeBox, SW_HIDE );
RestoreOwnerScrollInfo(hwndClpbrd);
InvalidateRect ( hwndClpbrd, NULL, TRUE );
}
else
{
// Change the character dimensions based on the format.
ChangeCharDimensions(hwndClpbrd, wOldFormat, wNewFormat);
// Initialize the owner display scroll info, because the
// contents have changed.
InitOwnerScrollInfo();
// Force a total repaint. fOwnerDisplay gets updated during
// a total repaint.
InvalidateRect(hwndClpbrd, NULL, TRUE);
ResetScrollInfo(hwndClpbrd);
// force update here BEFORE sending on WM_DRAWCLIPBOARD
UpdateWindow (hwndClpbrd);
}
}
}
SetCursor (hCursor);
}
// Pass the message on to the next clipboard viewer in the chain.
if (hwndNextViewer != NULL)
{
SendMessage(hwndNextViewer, WM_DRAWCLIPBOARD, 0, 0);
}
}
LRESULT OnEraseBkgnd(
HWND hwnd,
HDC hdc)
{
return DefMDIChildProc(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L);
}
LRESULT OnPaint(
HWND hwnd)
{
PMDIINFO pMDI;
PAINTSTRUCT ps;
HPALETTE hpal;
HPALETTE hpalT;
HBRUSH hbr;
LRESULT lRet = ONPAINT_FAIL;
HCURSOR hCursor;
if (!(pMDI = GETMDIINFO(hwnd)))
{
return ONPAINT_FAIL;
}
hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
if ( IsIconic ( hwnd ))
{
BeginPaint(hwnd, &ps);
if ( pMDI->flags & F_CLPBRD )
{
DrawIcon ( ps.hdc, 0, 0, hicClipbrd);
}
else if ( pMDI->flags & F_LOCAL )
{
DrawIcon ( ps.hdc, 0, 0, hicClipbook);
}
else
{
DrawIcon ( ps.hdc, 0, 0, hicRemote);
}
lRet = ONPAINT_SUCCESS;
goto donePaint;
}
if (pMDI->DisplayMode != DSP_PAGE)
{
BeginPaint (hwnd, &ps);
lRet = ONPAINT_FAIL;
goto donePaint;
}
if (fAppShuttingDown)
{
BeginPaint (hwnd, &ps);
lRet = ONPAINT_FAIL;
goto donePaint;
}
if (!VOpenClipboard( pMDI->pVClpbrd, hwnd))
{
#if DEBUG
SetStatusBarText("Clipboard changed but could not open");
#endif
lRet = ONPAINT_NOCLIPBRD;
goto done;
}
BeginPaint (hwnd, &ps);
// Fill background with proper color - DefMDIChildProc fills with app_workspace.
hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
FillRect(ps.hdc, &ps.rcPaint, hbr);
DeleteObject(hbr);
SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT));
if (hpal = VGetClipboardData( pMDI->pVClpbrd, CF_PALETTE))
{
PINFO("Palette found, selecting & realizing\r\n");
hpalT = SelectPalette(ps.hdc, hpal, pMDI != pActiveMDI );
RealizePalette(ps.hdc);
}
DrawStuff( hwnd, &ps, hwnd );
if (hpal)
{
// We don't want to put the DEFAULT palette in the foreground.
SelectPalette(ps.hdc, hpalT, FALSE);
}
VCloseClipboard( pMDI->pVClpbrd );
lRet = ONPAINT_SUCCESS;
donePaint:
EndPaint(hwnd, &ps);
done:
SetCursor (hCursor);
return lRet;
}
LRESULT CALLBACK FrameWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
int tmp;
// PINFO(TEXT("FrameWnd Msg: %u %ld %ld\r\n"), msg, wParam, lParam);
switch (msg)
{
case WM_CREATE:
{
CLIENTCREATESTRUCT ccs;
RECT rc;
/* Find window menu where children will be listed */
ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd), WINDOW_MENU_INDEX );
ccs.idFirstChild = 4100; // IDM_WINDOWCHILD;
// initialize special case clipboard formats...
// note that CF_BITMAP, CF_METAFILEPICT, CF_PALETTE are
// re-registered in a private format because data for these
// formats is exchanged between this app and clipsrv.exe in
// a flat DDEML data handle - not the regular DDE interpretation
// of a handle that carries those format IDs
if (LoadString (hInst, CF_BITMAP, szBuf, SZBUFSIZ))
cf_bitmap = RegisterClipboardFormat (szBuf);
if (LoadString (hInst, CF_METAFILEPICT, szBuf, SZBUFSIZ))
cf_metafilepict = RegisterClipboardFormat (szBuf);
if (LoadString (hInst, CF_PALETTE, szBuf, SZBUFSIZ))
cf_palette = RegisterClipboardFormat (szBuf);
cf_preview = RegisterClipboardFormat (SZPREVNAME);
cf_link = RegisterClipboardFormat (SZLINK);
cf_linkcopy = RegisterClipboardFormat (SZLINKCOPY);
cf_objectlink = RegisterClipboardFormat (SZOBJECTLINK);
cf_objectlinkcopy = RegisterClipboardFormat (SZOBJECTLINKCOPY);
CreateTools( hwnd ); // creates toolbar window, brushes, etc.
// determine height of toolbar window and save...
GetClientRect ( hwndToolbar, &rc );
dyButtonBar = rc.bottom - rc.top +1;
// determine height of statusbar window and save...
GetClientRect ( hwndStatus, &rc );
dyStatus = rc.bottom - rc.top;
// Create the MDI client - will be sized later
hwndMDIClient = CreateWindow ("mdiclient",
NULL,
WS_BORDER|
WS_CHILD|
WS_CLIPCHILDREN|
MDIS_ALLCHILDSTYLES|
WS_HSCROLL|
WS_VSCROLL,
0,
0,
0,
0,
hwnd,
(HMENU)0xCAC,
hInst,
(LPVOID)&ccs);
ShowWindow ( hwndMDIClient, SW_SHOW );
}
break;
case WM_QUERYNEWPALETTE:
// Tell the active document to realize in foreground.
if ( hwndActiveChild )
tmp = (WORD)SendMessage(hwndActiveChild, WM_QUERYNEWPALETTE,0, 0L);
else
break;
// If mapping is unchanged, other documents could still change,
// so give them a change to realize.
if (!tmp)
SendMessageToKids(WM_PALETTECHANGED, (WPARAM)hwndActiveChild, 0L);
return(tmp);
break;
// System palette has changed, so pass it on to the children.
case WM_PALETTECHANGED:
SendMessageToKids(WM_PALETTECHANGED, wParam, lParam);
break;
case WM_MENUSELECT:
PINFO(TEXT("MenuSelect %lx\r\n"), wParam);
// no context menu help for popup entries
if ( HIWORD(wParam) & MF_POPUP )
{
dwCurrentHelpId = 0;
}
else if ( HIWORD(wParam) & MF_SYSMENU )
{
dwCurrentHelpId = IDH_SYSMENU;
}
else
{
// We don't care if the menuitem's disabled, checked, whatever...
wParam = LOWORD(wParam);
// was this a dynamically added clipboard entry?
if (( wParam >= 0xc000 && wParam <= 0xffff || // registerd format?
wParam >= CF_TEXT && wParam <= CF_ENHMETAFILE || // intrinsic format?
wParam >= CF_OWNERDISPLAY && wParam <= CF_DSPMETAFILEPICT )
// gotta exclude sc_ stuff - overlaps with formats
&& ! ( wParam >= SC_SIZE && wParam <= SC_HOTKEY ) )
{
GetMenuString ( GetMenu(hwnd), (UINT)wParam,
szBuf2, SZBUFSIZ, MF_BYCOMMAND );
//Localized FE build uses "Bitmap(&B)" instead of "&Bitmap" in menu string.
StripAcceleratorKey( szBuf2 );
//For non-localized string
StripCharRange ( szBuf2, '&', '&' );
StringCchPrintf( szBuf, sizeof(szBuf), szViewHelpFmt, (LPSTR)szBuf2 );
SendMessage( hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)szBuf );
dwCurrentHelpId = (DWORD)(IDH_FORMATS_BASE + wParam);
break;
}
if ( wParam >= 4100 && wParam <= 4200 )
{
GetMenuString (GetMenu(hwnd), (UINT)wParam,szBuf2,SZBUFSIZ, MF_BYCOMMAND);
StripCharRange ( szBuf2, '&', '&' );
StripCharRange ( szBuf2, '0', '9' );
StringCchPrintf( szBuf, sizeof(szBuf), szActivateFmt,
*szBuf2 == ' ' ? (LPSTR)(szBuf2+1) : (LPSTR)szBuf2 );
SendMessage( hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)(LPSTR)szBuf );
dwCurrentHelpId = IDH_NAMESWIND;
break;
}
dwCurrentHelpId = (DWORD)(IDH_BASE + wParam);
}
MenuHelp( (WORD)msg, wParam, lParam, GetMenu(hwnd), hInst, hwndStatus, nIDs );
break;
case WM_F1DOWN:
PINFO(TEXT("Help on context %ld\r\n"), dwCurrentHelpId);
if ( dwCurrentHelpId )
{
WinHelp(hwndApp, szHelpFile, HELP_CONTEXT, dwCurrentHelpId );
DrawMenuBar(hwndApp);
}
break;
case WM_DRAWITEM:
HandleOwnerDraw( hwnd, msg, wParam, lParam );
break;
case WM_INITMENU:
InitializeMenu ((HMENU)wParam);
UpdateCBMenu ( hwnd, hwndActiveChild );
break;
case WM_SYSCOLORCHANGE:
DeleteTools( hwnd );
CreateTools( hwnd );
break;
case WM_COMMAND:
return ClipBookCommand ( hwnd, msg, wParam, lParam );
case WM_CLOSE:
#if DEBUG
if ( fAppLockedState )
PERROR(TEXT("Very bad: WM_CLOSE while locked\n\r"));
#endif
// force all clipboard formats rendered before exiting
// so we don't end up yielding in WM_RENDERALLFORMATS
// and get into trouble.
fAppShuttingDown = TRUE;
ForceRenderAll(hwnd, (PVCLPBRD)NULL );
PostMessage(hwnd, WM_CLOSE_REALLY, 0, 0L );
WinHelp(hwnd, szHelpFile, HELP_QUIT, 0L);
break;
case WM_NOTIFY:
{
LPTOOLTIPTEXT lpTTT = (LPTOOLTIPTEXT) lParam;
if (lpTTT->hdr.code == TTN_NEEDTEXT)
{
LoadString (hInst, (UINT)(MH_TOOLTIP + lpTTT->hdr.idFrom), lpTTT->szText, 80);
return TRUE;
}
}
break;
case WM_CLOSE_REALLY:
// this is necessary to avoid processing messages in our
// queue when we yield getting the clipboard data in
// ForceRenderAll and destroying the app prematurely
return DefFrameProc (hwnd,hwndMDIClient,WM_CLOSE,0,0L);
case WM_DESTROY:
#if DEBUG
if ( fAppLockedState )
{
PERROR(TEXT("Very bad: WM_DESTROY while locked\n\r"));
}
#endif
// Take us out of the viewer chain
ChangeClipboardChain(hwnd, hwndNextViewer);
DeleteTools ( hwnd );
Wpl.length = sizeof ( Wpl );
Wpl.flags = 0;
GetWindowPlacement ( hwnd, &Wpl );
SaveWindowPlacement ( &Wpl );
if (hkeyRoot != NULL)
{
RegSetValueEx (hkeyRoot, szStatusbar, 0L, REG_DWORD,
(LPBYTE)&fStatus, sizeof(fStatus));
RegSetValueEx (hkeyRoot, szToolbar, 0L, REG_DWORD,
(LPBYTE)&fToolBar, sizeof(fToolBar));
RegSetValueEx (hkeyRoot, szShPref, 0L, REG_DWORD,
(LPBYTE)&fSharePreference, sizeof(fSharePreference));
}
PostQuitMessage (0);
break;
case WM_DRAWCLIPBOARD:
OnDrawClipboard(hwnd);
break;
case WM_CHANGECBCHAIN:
if (hwndNextViewer == NULL)
return(FALSE);
if ( (HWND)wParam == hwndNextViewer)
{
hwndNextViewer = (HWND)lParam;
return(TRUE);
}
return(SendMessage(hwndNextViewer, WM_CHANGECBCHAIN, wParam, lParam));
case WM_RENDERALLFORMATS:
// WM_DESTROY follows close on the heels of this message, and
// we will process it and die while another copy of FrameWndProc
// is in sync DDEML transaction...
//
// Note that we now attempt to render all formats in WM_DESTROY
// before doing the PostQuitMessage so we should not have to
// respond to this message.
break;
case WM_RENDERFORMAT:
{
HDDEDATA hListData = 0L;
HDDEDATA hFmtData = 0L;
HSZ hszFmt = 0L;
LPTSTR lpszList = TEXT("");
LPTSTR q;
DWORD cbDataLen;
UINT RealFmt;
UINT uiErr;
PINFO(TEXT("Frame WM_RENDERFORMAT: %d\r\n"),wParam);
// If we did File/Save or File/Open then render from file.
// When we get IDM_COPY, szSaveFileName will assigned ""
if (szSaveFileName[0])
{
SetClipboardData((UINT)wParam, RenderFormatFromFile(szSaveFileName,
(WORD)wParam));
break;
}
if ( !IsWindow(hwndClpOwner))
{
PERROR(TEXT("Strange?: null clipboard owner window!\n\r"));
break;
}
DdeKeepStringHandle ( idInst, hszFormatList );
hListData = MySyncXact (NULL,
0L,
GETMDIINFO(hwndClpOwner)->hClpConv,
hszFormatList,
CF_TEXT,
XTYP_REQUEST,
SHORT_SYNC_TIMEOUT,
NULL);
if (!hListData && !fAppShuttingDown)
{
uiErr = DdeGetLastError (idInst);
PERROR (TEXT("WM_RENDERFORM: REQUEST for formatlist failed: %x\n\r"),uiErr);
MessageBoxID (hInst,
hwnd,
IDS_DATAUNAVAIL,
IDS_APPNAME,
MB_OK|MB_ICONEXCLAMATION);
break;
}
lpszList = (LPTSTR)DdeAccessData ( hListData, &cbDataLen );
if (!lpszList && !fAppShuttingDown)
{
PERROR(TEXT("WM_RENDERFORM: DdeAccessData failed!\n\r"));
MessageBoxID (hInst,
hwnd,
IDS_DATAUNAVAIL,
IDS_APPNAME,
MB_OK|MB_ICONEXCLAMATION);
break;
}
for (q = strtokA (lpszList, "\t"); q; q = strtokA(NULL, "\t"))
{
RealFmt = MyGetFormat ( q, GETFORMAT_DONTLIE );
if ( wParam == RealFmt || msg == WM_RENDERALLFORMATS )
{
PINFO(TEXT("Getting format %d\r\n"), RealFmt);
hszFmt = DdeCreateStringHandle ( idInst, q, 0 );
hFmtData = MySyncXact (NULL,
0L,
GETMDIINFO(hwndClpOwner)->hClpConv,
hszFmt,
MyGetFormat (q, GETFORMAT_LIE),
XTYP_REQUEST,
LONG_SYNC_TIMEOUT,
NULL );
if (hFmtData)
{
SetClipboardFormatFromDDE ( hwndClpbrd, RealFmt , hFmtData );
}
else
PERROR(TEXT("REQUEST for %s failed %x\n\r"), q, DdeGetLastError(idInst));
DdeFreeStringHandle (idInst, hszFmt);
}
}
DdeUnaccessData( hListData );
DdeFreeDataHandle ( hListData );
// Couldn't find Bitmap, try DIB and
// and convert it to Bitmap.
if (wParam == CF_BITMAP && !hFmtData)
{
TCHAR szName[40];
GetClipboardName (CF_DIB, szName, sizeof (szName));
hszFmt = DdeCreateStringHandle (idInst, szName, 0);
hFmtData = MySyncXact (NULL,
0L,
GETMDIINFO (hwndClpOwner)->hClpConv,
hszFmt,
MyGetFormat (szName, GETFORMAT_LIE),
XTYP_REQUEST,
LONG_SYNC_TIMEOUT,
NULL);
if (hFmtData)
SetClipboardFormatFromDDE (hwndClpbrd, DDE_DIB2BITMAP, hFmtData);
DdeFreeStringHandle (idInst, hszFmt);
}
break;
}
case WM_SIZE:
SendMessage (hwndToolbar, WM_SIZE, 0, 0L);
SendMessage (hwndStatus, WM_SIZE, 0, 0L);
AdjustMDIClientSize();
break;
case WM_PARENTNOTIFY:
// PINFO(TEXT("Recieved WM_PARENTNOTIFY %d %ld\r\n"), wParam, lParam);
break;
default:
return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
LRESULT CALLBACK ChildWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
LPMEASUREITEMSTRUCT lpmisCtl;
HDC hdc;
int tmp;
PMDIINFO pMDI;
int i;
HPALETTE hCurrentPal, hOldPal;
// PERROR(TEXT("ChildWndProc msg: %u %ld %ld\r\n"),msg, wParam, lParam);
switch (msg)
{
case WM_MDIACTIVATE:
SendMessage(hwndMDIClient, WM_MDIREFRESHMENU, 0, 0);
DrawMenuBar(hwndApp);
if ((HWND)lParam != hwnd)
break;
// intentional fall through
case WM_SETFOCUS:
hwndActiveChild = hwnd;
if (!(pActiveMDI = GETMDIINFO(hwndActiveChild)))
break;
if ( pActiveMDI->DisplayMode != DSP_PAGE &&
IsWindow( pActiveMDI->hWndListbox ))
{
SetFocus ( pActiveMDI->hWndListbox );
}
else
{
SetFocus ( hwndActiveChild );
}
InitializeMenu( GetMenu(hwndApp) );
UpdateNofMStatus(hwndActiveChild);
return (DefMDIChildProc(hwnd, msg, wParam, lParam));
case WM_LBUTTONDBLCLK:
if (!GETMDIINFO(hwnd))
break;
if (GETMDIINFO (hwnd)->DisplayMode == DSP_PAGE &&
!(GETMDIINFO(hwnd)->flags & F_CLPBRD ))
{
if (GETMDIINFO(hwnd)->OldDisplayMode == DSP_LIST )
SendMessage ( hwndApp, WM_COMMAND, IDM_LISTVIEW, 0L );
else if ( GETMDIINFO(hwnd)->OldDisplayMode == DSP_PREV )
SendMessage ( hwndApp, WM_COMMAND, IDM_PREVIEWS, 0L );
}
break;
case WM_PALETTECHANGED:
if (hwnd == (HWND)wParam)
break;
// intentional fall through
case WM_QUERYNEWPALETTE:
if (!GETMDIINFO(hwnd))
break;
if (GETMDIINFO(hwnd)->DisplayMode != DSP_PAGE)
return 0;
i = 0;
if (VOpenClipboard( GETMDIINFO(hwnd)->pVClpbrd, hwnd))
{
if ( hCurrentPal = VGetClipboardData( GETMDIINFO(hwnd)->pVClpbrd, CF_PALETTE))
{
hdc = GetDC(hwnd);
hOldPal = SelectPalette (hdc,
hCurrentPal,
(msg == WM_QUERYNEWPALETTE)? FALSE: TRUE);
i = RealizePalette(hdc);
SelectPalette(hdc, hOldPal, TRUE);
RealizePalette(hdc);
ReleaseDC(hwnd, hdc);
if (i)
InvalidateRect(hwnd, NULL, TRUE);
}
VCloseClipboard( GETMDIINFO(hwnd)->pVClpbrd );
}
return(i);
break;
case WM_MENUSELECT:
MenuHelp ((WORD)msg,
wParam,
lParam,
GetMenu(hwndApp),
hInst,
hwndStatus,
nIDs);
break;
case WM_CREATE:
if ((pMDI = (LPMDIINFO)GlobalAllocPtr(GPTR, sizeof(MDIINFO))) == NULL)
{
PERROR(TEXT("MdiInfo alloc failed\n\r"));
break;
}
SetWindowLongPtr (hwnd, GWL_MDIINFO, (LONG_PTR)pMDI);
pMDI->DisplayMode = DSP_LIST;
pMDI->hExeConv = 0L;
pMDI->hClpConv = 0L;
pMDI->hVClpConv = 0L;
pMDI->flags = 0L;
pMDI->CurSelFormat = CBM_AUTO;
pMDI->cyScrollLast = -1L;
pMDI->cxScrollLast = -1;
pMDI->cyScrollNow = 0L;
pMDI->cxScrollNow = 0;
pMDI->pVClpbrd = NULL;
pMDI->hszConvPartner = 0L;
pMDI->hszConvPartnerNP = 0L;
pMDI->hszClpTopic = 0L;
pMDI->fDisplayFormatChanged = TRUE;
pMDI->hWndListbox = CreateWindow (TEXT("listbox"),
szNull,
WS_CHILD |
LBS_STANDARD |
LBS_NOINTEGRALHEIGHT |
LBS_LISTVIEW,
0,
0,
100,
100,
hwnd,
(HMENU)ID_LISTBOX,
hInst,
0L );
// create the scroll bars
pMDI->hwndVscroll = CreateWindowW (L"scrollbar",
L"",
WS_CHILD|SBS_VERT,
0,
0,
0,
0,
hwnd,
(HMENU)ID_VSCROLL,
hInst,
0L);
pMDI->hwndHscroll = CreateWindowW (L"scrollbar",
L"",
WS_CHILD|SBS_HORZ,
0,
0,
0,
0,
hwnd,
(HMENU)ID_VSCROLL,
hInst,
0L);
// create the corner size box
pMDI->hwndSizeBox = CreateWindowW (L"scrollbar",
L"",
WS_CHILD|SBS_SIZEBOX,
0,
0,
0,
0,
hwnd,
(HMENU)ID_SIZEBOX,
hInst,
0L);
// create the page fwd/bkwd buttons
pMDI->hwndPgUp = CreateWindowW (L"button",
L"",
WS_CHILD | BS_OWNERDRAW,
0,
0,
0,
0,
hwnd,
(HMENU)ID_PAGEUP,
hInst,
0L);
pMDI->hwndPgDown = CreateWindowW (L"button",
L"",
WS_CHILD | BS_OWNERDRAW,
0,
0,
0,
0,
hwnd,
(HMENU)ID_PAGEDOWN,
hInst,
0L);
SetCharDimensions( hwnd, GetStockObject (SYSTEM_FONT));
break;
case WM_VSCROLL:
if (wParam != SB_THUMBTRACK)
{
if (fOwnerDisplay)
SendOwnerMessage (WM_VSCROLLCLIPBOARD, (WPARAM)hwnd, (LPARAM)wParam);
else
ClipbrdVScroll (hwnd, LOWORD(wParam), HIWORD(wParam));
}
break;
case WM_HSCROLL:
if (wParam != SB_THUMBTRACK)
{
if (fOwnerDisplay)
SendOwnerMessage (WM_HSCROLLCLIPBOARD, (WPARAM)hwnd, (LPARAM)wParam);
else
ClipbrdHScroll (hwnd, LOWORD(wParam), HIWORD(wParam));
}
break;
case WM_QUERYDRAGICON:
if (!GETMDIINFO(hwnd))
break;
if (GETMDIINFO(hwnd)->flags & F_CLPBRD)
return (LRESULT)hcurClipbrd;
else if ( GETMDIINFO(hwnd)->flags & F_LOCAL )
return (LRESULT)hcurClipbook;
else
return (LRESULT)hcurRemote;
case WM_CLOSE:
if (!GETMDIINFO(hwnd))
{
if (!(GETMDIINFO(hwnd)->flags & (F_CLPBRD | F_LOCAL)))
{
PINFO(TEXT("removing reconn for '%s'\n\r"), (LPSTR)GETMDIINFO(hwnd)->szBaseName);
if (NULL != hkeyRoot)
{
StringCchCopy(szBuf, SZBUFSIZ, GETMDIINFO(hwnd)->szBaseName);
StringCchCat( szBuf, SZBUFSIZ, szConn);
RegDeleteValue(hkeyRoot, szBuf);
StringCchCopy(szBuf, SZBUFSIZ, GETMDIINFO(hwnd)->szBaseName);
StringCchCat (szBuf, SZBUFSIZ, szWindows);
RegDeleteValue(hkeyRoot, szBuf);
}
}
}
WinHelp(hwnd, szHelpFile, HELP_QUIT, 0L);
return(DefMDIChildProc(hwnd, msg, wParam, lParam));
case WM_PAINT:
switch (OnPaint(hwnd))
{
case ONPAINT_SUCCESS: return TRUE;
case ONPAINT_FAIL: return FALSE;
case ONPAINT_NOCLIPBRD: PostMessage (hwnd, msg, wParam, lParam);
default: return FALSE;
}
break;
case WM_KEYDOWN:
{
WORD sb;
if (!(pMDI = GETMDIINFO(hwnd)))
break;
if ( pMDI->DisplayMode != DSP_PAGE )
return (DefMDIChildProc(hwnd, msg, wParam, lParam));
switch (wParam)
{
case VK_UP:
sb = SB_LINEUP;
goto VertScroll;
case VK_DOWN:
sb = SB_LINEDOWN;
goto VertScroll;
case VK_PRIOR:
sb = SB_PAGEUP;
goto VertScroll;
case VK_NEXT:
sb = SB_PAGEDOWN;
VertScroll:
SendMessage(hwnd, WM_VSCROLL, sb, 0L);
break;
case VK_LEFT:
sb = SB_LINEUP;
goto HorzScroll;
case VK_RIGHT:
sb = SB_LINEDOWN;
goto HorzScroll;
case VK_TAB:
sb = (GetKeyState( VK_SHIFT ) < 0) ? SB_PAGEUP : SB_PAGEDOWN;
HorzScroll:
SendMessage( hwnd, WM_HSCROLL, sb, 0L);
break;
default:
return (DefMDIChildProc(hwnd, msg, wParam, lParam));
}
}
break;
case WM_SIZE:
if (!(pMDI = GETMDIINFO(hwnd)))
break;
AdjustControlSizes( hwnd );
pMDI->fDisplayFormatChanged = TRUE;
InvalidateRect (hwnd, NULL, FALSE);
if ( pMDI->DisplayMode == DSP_PAGE )
ResetScrollInfo ( hwnd );
return (DefMDIChildProc(hwnd, msg, wParam, lParam));
case WM_DRAWITEM:
HandleOwnerDraw( hwnd, msg, wParam, lParam );
break;
case WM_COMPAREITEM:
if ( wParam != ID_LISTBOX )
break;
tmp = lstrcmpi (&((LPLISTENTRY)((LPCOMPAREITEMSTRUCT)lParam)->itemData1)->name[1],
&((LPLISTENTRY)((LPCOMPAREITEMSTRUCT)lParam)->itemData2)->name[1]);
if ( tmp < 0 )
{
return -1;
}
else if (tmp > 0)
{
return 1;
}
else
{
return 0;
}
break;
case WM_DELETEITEM:
if ( wParam != ID_LISTBOX )
break;
// if item is marked for saving (for a new listbox), dont delete
if ( ((LPLISTENTRY)((LPDELETEITEMSTRUCT)lParam)->itemData)->fDelete == FALSE )
break;
// delete preview bmp if there is one
if (((LPLISTENTRY)((LPDELETEITEMSTRUCT)lParam)->itemData)->hbmp)
DeleteObject (((LPLISTENTRY)((LPDELETEITEMSTRUCT)lParam)->itemData)->hbmp);
GlobalFreePtr( (LPVOID)((LPDELETEITEMSTRUCT)lParam)->itemData );
break;
case WM_MEASUREITEM:
lpmisCtl = (MEASUREITEMSTRUCT *) lParam;
switch ( wParam )
{
case ID_LISTBOX:
if (!GETMDIINFO(hwnd))
break;
if (GETMDIINFO(hwnd)->DisplayMode == DSP_LIST)
lpmisCtl->itemHeight = max( LSTBTDY, dyPrevFont + 1);
else
lpmisCtl->itemHeight = 3*dyPrevFont + PREVBMPSIZ + 2*PREVBRD;
break;
case ID_PAGEUP:
case ID_PAGEDOWN:
lpmisCtl->itemWidth = GetSystemMetrics ( SM_CXHSCROLL );
lpmisCtl->itemHeight = GetSystemMetrics ( SM_CYVSCROLL );
break;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_LISTBOX:
if (!GETMDIINFO(hwnd))
break;
if (!(IsWindow(GETMDIINFO(hwnd)->hWndListbox)))
break;
switch(HIWORD(wParam))
{
case LBN_SETFOCUS:
case LBN_SELCHANGE:
UpdateNofMStatus(hwnd);
InitializeMenu( GetMenu(hwndApp));
break;
case LBN_SELCANCEL:
case LBN_KILLFOCUS:
break;
case LBN_DBLCLK:
// Double-clicks cause me to go to page view
SendMessage (hwndApp, WM_COMMAND, IDM_PAGEVIEW, 0L);
break;
}
break;
case ID_PAGEUP:
case ID_PAGEDOWN:
SendMessage ( hwndApp, WM_COMMAND, wParam, 0L );
break;
default:
return(DefMDIChildProc(hwnd, WM_COMMAND, wParam, lParam));
}
break;
case WM_SYSCOMMAND:
// The Close menuitem on the system menus of the clipboard and
// local clipbook windows should be greyed, so we shouldn't get
// that message.
switch ( wParam )
{
case SC_CLOSE:
if (!GETMDIINFO(hwnd))
break;
// don't allow close of local or clipboard
if (GETMDIINFO(hwnd)->flags & (F_LOCAL | F_CLPBRD))
wParam = SC_MINIMIZE;
break;
default:
break;
}
return DefMDIChildProc(hwnd, msg, wParam, lParam );
case WM_DESTROY:
if (!(pMDI = GETMDIINFO(hwnd)))
break;
DdeDisconnect( pMDI->hExeConv );
if (pMDI->hClpConv)
DdeDisconnect ( pMDI->hClpConv );
if (pMDI->hVClpConv)
DdeDisconnect ( pMDI->hVClpConv );
if (pMDI->hszConvPartner)
DdeFreeStringHandle ( idInst, pMDI->hszConvPartner );
if (pMDI->hszConvPartnerNP)
DdeFreeStringHandle ( idInst, pMDI->hszConvPartnerNP );
if (pMDI->hszClpTopic)
DdeFreeStringHandle ( idInst, pMDI->hszClpTopic );
if (pMDI->hszVClpTopic)
DdeFreeStringHandle ( idInst, pMDI->hszVClpTopic );
if (pMDI->pVClpbrd)
DestroyVClipboard ( pMDI->pVClpbrd );
if (hwnd == hwndLocal)
hwndLocal = NULL;
if (hwnd == hwndClpbrd)
hwndClpbrd = NULL;
// free up the MDI info struct
GlobalFree ( (HGLOBAL)pMDI );
break;
default:
return (DefMDIChildProc(hwnd, msg, wParam, lParam));
}
return 0L;
}
/****************************************************************************
*
* FUNCTION : SendMessageToKids
*
* PURPOSE : Send the given message with the given parameters to all
* of the MDI child windows.
*
* RETURNS : None.
*
****************************************************************************/
VOID SendMessageToKids(
WORD msg,
WPARAM wParam,
LPARAM lParam)
{
register HWND hwndT;
hwndT = GetWindow (hwndMDIClient, GW_CHILD);
while (hwndT)
{
SendMessage (hwndT, msg, wParam, lParam);
hwndT = GetWindow(hwndT, GW_HWNDNEXT);
}
}
BOOL SyncOpenClipboard(
HWND hwnd)
{
BOOL fOK;
if (!fClpOpen)
{
// PINFO(TEXT("\r\nClipbook: Opening Clipboard\r\n"));
WaitForSingleObject(hmutexClp, 0); //INFINITE);
fOK = OpenClipboard(hwnd);
if (!fOK)
{
PERROR("OpenClipboard failed\r\n");
ReleaseMutex(hmutexClp);
}
else
{
fClpOpen = TRUE;
}
return fOK;
}
else
{
PERROR("Attempt at opening clipboard twice!\r\n");
return(FALSE);
}
return fOK;
}
BOOL SyncCloseClipboard (void)
{
BOOL fOK;
// PINFO(TEXT("\r\nClipbook: Closing Clipboard\r\n"));
fOK = CloseClipboard();
ReleaseMutex(hmutexClp);
if (!fOK)
{
PERROR("CloseClipboard failed\r\n");
}
fClpOpen = FALSE;
return fOK;
}