617 lines
15 KiB
C++
617 lines
15 KiB
C++
/**************************************************************************
|
|
THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
|
|
Copyright 1999 - 2000 Microsoft Corporation. All Rights Reserved.
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
|
|
File: EnumDesk.cpp
|
|
|
|
Description:
|
|
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
#include statements
|
|
**************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <commctrl.h>
|
|
#include <shlobj.h>
|
|
#include "EnumDesk.h"
|
|
#include "Tree.h"
|
|
#include "List.h"
|
|
#include "resource.h"
|
|
|
|
/**************************************************************************
|
|
function prototypes
|
|
**************************************************************************/
|
|
|
|
int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
|
|
BOOL Main_InitApplication(HINSTANCE);
|
|
BOOL Main_InitInstance(HINSTANCE, int);
|
|
LRESULT CALLBACK Main_WndProc(HWND, UINT, WPARAM, LPARAM);
|
|
HIMAGELIST Main_CreateImageList(BOOL);
|
|
void Main_SizeChildren(HWND);
|
|
void Main_UpdateMenu(HWND, HMENU);
|
|
LRESULT Main_OnCommand(HWND, WPARAM, LPARAM);
|
|
|
|
/**************************************************************************
|
|
global variables and definitions
|
|
**************************************************************************/
|
|
|
|
HINSTANCE g_hInst;
|
|
TCHAR g_szClassName[] = TEXT("EnumDeskWndClass");
|
|
HWND g_hwndMain;
|
|
LPMALLOC g_pMalloc;
|
|
UINT g_uPosition;
|
|
IContextMenu2 *g_pcm2;
|
|
|
|
#define GAP_SIZE 2
|
|
#define MIN_SIZE 10
|
|
|
|
/******************************************************************************
|
|
|
|
WinMain
|
|
|
|
******************************************************************************/
|
|
|
|
int PASCAL WinMain( HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpCmdLine);
|
|
|
|
MSG msg;
|
|
|
|
g_hInst = hInstance;
|
|
|
|
if(!hPrevInstance)
|
|
if(!Main_InitApplication(hInstance))
|
|
return FALSE;
|
|
|
|
CoInitialize(NULL);
|
|
|
|
//required to use the common controls
|
|
InitCommonControls();
|
|
|
|
/* Perform initializations that apply to a specific instance */
|
|
|
|
if (!Main_InitInstance(hInstance, nCmdShow))
|
|
return FALSE;
|
|
|
|
/* Acquire and dispatch messages until a WM_QUIT uMessage is received. */
|
|
|
|
HACCEL hAccels = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELS));
|
|
|
|
while(GetMessage( &msg, NULL, 0x00, 0x00))
|
|
{
|
|
if(!TranslateAccelerator(g_hwndMain, hAccels, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return (int)msg.wParam;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
Main_InitApplication
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL Main_InitApplication(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
/* Fill in window class structure with parameters that describe the main window. */
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = (WNDPROC)Main_WndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
|
wc.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_SPLIT_CURSOR));
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
|
wc.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN_MENU);
|
|
wc.lpszClassName = g_szClassName;
|
|
|
|
/* Register the window class and return success/failure code. */
|
|
|
|
return RegisterClass(&wc);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
Main_InitInstance
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL Main_InitInstance( HINSTANCE hInstance,
|
|
int nCmdShow)
|
|
{
|
|
/* Create a main window for this application instance. */
|
|
|
|
g_hwndMain = CreateWindowEx( 0,
|
|
g_szClassName,
|
|
TEXT("New EnumDesk Sample"),
|
|
WS_OVERLAPPEDWINDOW,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL);
|
|
|
|
/* If window could not be created, return "failure" */
|
|
|
|
if(!g_hwndMain)
|
|
return FALSE;
|
|
|
|
/* Make the window visible; update its client area; and return "success" */
|
|
|
|
ShowWindow(g_hwndMain, nCmdShow);
|
|
UpdateWindow(g_hwndMain);
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
Main_WndProc
|
|
|
|
******************************************************************************/
|
|
|
|
LRESULT CALLBACK Main_WndProc(HWND hWnd,
|
|
UINT uMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMessage)
|
|
{
|
|
case WM_NCCREATE:
|
|
SHGetMalloc(&g_pMalloc);
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
{
|
|
HIMAGELIST himlLarge;
|
|
HIMAGELIST himlSmall;
|
|
HWND hwndTree;
|
|
HWND hwndList;
|
|
|
|
g_uPosition = 0;
|
|
|
|
//get the system image lists
|
|
himlLarge = Main_CreateImageList(TRUE);
|
|
himlSmall = Main_CreateImageList(FALSE);
|
|
|
|
// create the TreeView control
|
|
hwndTree = Tree_Create(g_hInst, hWnd, himlSmall);
|
|
|
|
// create the ListView control
|
|
hwndList = List_Create(g_hInst, hWnd, himlLarge, himlSmall);
|
|
|
|
//initialize the TreeView control
|
|
Tree_Init(hwndTree);
|
|
|
|
SetFocus(hwndTree);
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR pnmh = (LPNMHDR) lParam;
|
|
|
|
switch(pnmh->idFrom)
|
|
{
|
|
case IDC_TREEVIEW:
|
|
return Tree_Notify(hWnd, lParam);
|
|
|
|
case IDC_LISTVIEW:
|
|
return List_Notify(hWnd, lParam);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case WM_SIZE:
|
|
{
|
|
Main_SizeChildren(hWnd);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
SetCapture(hWnd);
|
|
return 0;
|
|
|
|
case WM_LBUTTONUP:
|
|
ReleaseCapture();
|
|
return 0;
|
|
|
|
case WM_MOUSEMOVE:
|
|
//if the left button is down
|
|
if(GetKeyState(VK_LBUTTON) & 0x8000)
|
|
{
|
|
RECT rc;
|
|
|
|
GetClientRect(hWnd, &rc);
|
|
|
|
//don't do anything if we are already at the minimum size
|
|
if((g_uPosition == MIN_SIZE) && (LOWORD(lParam) <= MIN_SIZE))
|
|
break;
|
|
|
|
//don't do anything if we are already at the maximum size
|
|
if(((rc.right - g_uPosition) == MIN_SIZE) && (LOWORD(lParam) >= g_uPosition))
|
|
break;
|
|
|
|
g_uPosition = LOWORD(lParam);
|
|
|
|
//check for min and max
|
|
if(g_uPosition < MIN_SIZE)
|
|
g_uPosition = MIN_SIZE;
|
|
|
|
if((rc.right - g_uPosition) < MIN_SIZE)
|
|
g_uPosition = rc.right - MIN_SIZE;
|
|
|
|
Main_SizeChildren(hWnd);
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
return Main_OnCommand(hWnd, wParam, lParam);
|
|
|
|
case WM_DESTROY:
|
|
//tell the list to release its current folder
|
|
List_ReleaseCurrentFolder();
|
|
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_NCDESTROY:
|
|
g_pMalloc->Release();
|
|
g_pMalloc = NULL;
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
{
|
|
HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE);
|
|
|
|
hbr = (HBRUSH)SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)hbr);
|
|
|
|
if(hbr)
|
|
DeleteObject(hbr);
|
|
}
|
|
break;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
Main_UpdateMenu(hWnd, (HMENU)wParam);
|
|
//fall through
|
|
|
|
case WM_DRAWITEM:
|
|
case WM_MENUCHAR:
|
|
case WM_MEASUREITEM:
|
|
if(g_pcm2)
|
|
{
|
|
g_pcm2->HandleMenuMsg(uMessage, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
POINT ptScreen;
|
|
POINT ptClient;
|
|
|
|
ptScreen.x = GET_X_LPARAM(lParam);
|
|
ptScreen.y = GET_Y_LPARAM(lParam);
|
|
ptClient = ptScreen;
|
|
ScreenToClient(hWnd, &ptClient);
|
|
HWND hwndOver = ChildWindowFromPoint(hWnd, ptClient);
|
|
|
|
if(GetDlgItem(hWnd, IDC_TREEVIEW) == hwndOver)
|
|
{
|
|
Tree_DoContextMenu(hwndOver, &ptScreen);
|
|
}
|
|
else if(GetDlgItem(hWnd, IDC_LISTVIEW) == hwndOver)
|
|
{
|
|
List_DoContextMenu(hwndOver, &ptScreen);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return DefWindowProc(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
Main_CreateImageList
|
|
|
|
******************************************************************************/
|
|
|
|
HIMAGELIST Main_CreateImageList(BOOL fLarge)
|
|
{
|
|
HIMAGELIST hImageList;
|
|
SHFILEINFO sfi;
|
|
|
|
//get the system image list
|
|
hImageList = (HIMAGELIST)SHGetFileInfo( TEXT("C:\\"),
|
|
0,
|
|
&sfi,
|
|
sizeof(SHFILEINFO),
|
|
SHGFI_SYSICONINDEX | (fLarge ? 0 : SHGFI_SMALLICON));
|
|
|
|
return hImageList;
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
Main_SizeChildren
|
|
|
|
******************************************************************************/
|
|
|
|
void Main_SizeChildren(HWND hwndParent)
|
|
{
|
|
RECT rc;
|
|
|
|
GetClientRect(hwndParent, &rc);
|
|
|
|
if(!g_uPosition)
|
|
{
|
|
g_uPosition = rc.right/3;
|
|
}
|
|
|
|
//resize the TreeView control
|
|
MoveWindow( GetDlgItem(hwndParent, IDC_TREEVIEW),
|
|
0,
|
|
0,
|
|
g_uPosition - GAP_SIZE,
|
|
rc.bottom,
|
|
TRUE);
|
|
|
|
//resize the ListView
|
|
MoveWindow( GetDlgItem(hwndParent, IDC_LISTVIEW),
|
|
g_uPosition,
|
|
0,
|
|
rc.right - g_uPosition,
|
|
rc.bottom,
|
|
TRUE);
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
Main_UpdateMenu
|
|
|
|
******************************************************************************/
|
|
|
|
void Main_UpdateMenu(HWND hWnd, HMENU hMenu)
|
|
{
|
|
UINT uID = 0;
|
|
DWORD dwStyle;
|
|
|
|
//uncheck all of these guys
|
|
CheckMenuItem(hMenu, IDM_LARGE_ICONS, MF_BYCOMMAND | MF_UNCHECKED);
|
|
CheckMenuItem(hMenu, IDM_SMALL_ICONS, MF_BYCOMMAND | MF_UNCHECKED);
|
|
CheckMenuItem(hMenu, IDM_LIST, MF_BYCOMMAND | MF_UNCHECKED);
|
|
|
|
//check the appropriate view menu item
|
|
dwStyle = GetWindowLong(GetDlgItem(hWnd, IDC_LISTVIEW), GWL_STYLE);
|
|
switch(dwStyle & LVS_TYPEMASK)
|
|
{
|
|
case LVS_ICON:
|
|
uID = IDM_LARGE_ICONS;
|
|
break;
|
|
|
|
case LVS_SMALLICON:
|
|
uID = IDM_SMALL_ICONS;
|
|
break;
|
|
|
|
case LVS_LIST:
|
|
uID = IDM_LIST;
|
|
break;
|
|
}
|
|
CheckMenuRadioItem(hMenu, IDM_LARGE_ICONS, IDM_LIST, uID, MF_BYCOMMAND | MF_CHECKED);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Main_OnCommand()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT Main_OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDM_EXIT:
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
|
|
case IDM_LARGE_ICONS:
|
|
{
|
|
HWND hwndListView = GetDlgItem(hWnd, IDC_LISTVIEW);
|
|
DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
|
|
SetWindowLong(hwndListView, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | LVS_ICON);
|
|
}
|
|
break;
|
|
|
|
case IDM_SMALL_ICONS:
|
|
{
|
|
HWND hwndListView = GetDlgItem(hWnd, IDC_LISTVIEW);
|
|
DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
|
|
SetWindowLong(hwndListView, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | LVS_SMALLICON);
|
|
}
|
|
break;
|
|
|
|
case IDM_LIST:
|
|
{
|
|
HWND hwndListView = GetDlgItem(hWnd, IDC_LISTVIEW);
|
|
DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
|
|
SetWindowLong(hwndListView, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | LVS_LIST);
|
|
}
|
|
break;
|
|
|
|
|
|
case IDM_REFRESH:
|
|
List_Refresh(GetDlgItem(hWnd, IDC_LISTVIEW));
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Pidl_GetNextItem()
|
|
|
|
**************************************************************************/
|
|
|
|
inline LPITEMIDLIST Pidl_GetNextItem(LPCITEMIDLIST pidl)
|
|
{
|
|
if(pidl)
|
|
return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Pidl_Create()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST Pidl_Create(UINT cbSize)
|
|
{
|
|
LPITEMIDLIST pidl = NULL;
|
|
|
|
pidl = (LPITEMIDLIST) g_pMalloc->Alloc(cbSize);
|
|
if(pidl)
|
|
ZeroMemory(pidl, cbSize);
|
|
|
|
return pidl;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Pidl_GetSize()
|
|
|
|
**************************************************************************/
|
|
|
|
UINT Pidl_GetSize(LPCITEMIDLIST pidl)
|
|
{
|
|
UINT cbTotal = 0;
|
|
LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;
|
|
|
|
if(pidlTemp)
|
|
{
|
|
while(pidlTemp->mkid.cb)
|
|
{
|
|
cbTotal += pidlTemp->mkid.cb;
|
|
pidlTemp = Pidl_GetNextItem(pidlTemp);
|
|
}
|
|
|
|
// Requires a 16 bit zero value for the NULL terminator
|
|
cbTotal += 2 * sizeof(BYTE);
|
|
}
|
|
|
|
return cbTotal;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Pidl_Copy()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST Pidl_Copy(LPCITEMIDLIST pidlSource)
|
|
{
|
|
LPITEMIDLIST pidlTarget = NULL;
|
|
UINT cbSource = 0;
|
|
|
|
if(NULL == pidlSource)
|
|
return NULL;
|
|
|
|
//
|
|
// Allocate the new ITEMIDLIST
|
|
//
|
|
cbSource = Pidl_GetSize(pidlSource);
|
|
pidlTarget = (LPITEMIDLIST) g_pMalloc->Alloc(cbSource);
|
|
if(!pidlTarget)
|
|
return NULL;
|
|
|
|
//
|
|
// Copy the source to the target
|
|
//
|
|
CopyMemory(pidlTarget, pidlSource, cbSource);
|
|
|
|
return pidlTarget;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Pidl_Concatenate()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST Pidl_Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
|
{
|
|
LPITEMIDLIST pidlNew;
|
|
UINT cb1 = 0,
|
|
cb2 = 0;
|
|
|
|
//
|
|
// Pidl1 can possibly be NULL if it points to the desktop. Since we only
|
|
// need a single NULL terminator, we remove the extra 2 bytes from the
|
|
// size of the first ITEMIDLIST.
|
|
//
|
|
if(pidl1)
|
|
cb1 = Pidl_GetSize(pidl1) - (2 * sizeof(BYTE));
|
|
|
|
cb2 = Pidl_GetSize(pidl2);
|
|
|
|
//
|
|
// Create a new ITEMIDLIST that is the size of both pidl1 and pidl2, then
|
|
// copy pidl1 and pidl2 to the new list.
|
|
//
|
|
pidlNew = Pidl_Create(cb1 + cb2);
|
|
if(pidlNew)
|
|
{
|
|
if(pidl1)
|
|
CopyMemory(pidlNew, pidl1, cb1);
|
|
|
|
CopyMemory(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
|
|
}
|
|
|
|
return pidlNew;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Pidl_Free()
|
|
|
|
**************************************************************************/
|
|
|
|
void Pidl_Free(LPITEMIDLIST pidl)
|
|
{
|
|
if(pidl)
|
|
g_pMalloc->Free(pidl);
|
|
}
|
|
|