/**************************************************************************
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 1997 Microsoft Corporation. All Rights Reserved.
**************************************************************************/
/**************************************************************************
Include Files
**************************************************************************/
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "VListVw.h"
/**************************************************************************
Local Function Prototypes
**************************************************************************/
#define ErrorHandler() ErrorHandlerEx(__LINE__, __FILE__)
void ErrorHandlerEx(WORD, LPSTR);
LRESULT ListViewNotify(HWND, LPARAM);
void SwitchView(HWND, DWORD);
BOOL DoContextMenu(HWND, WPARAM, LPARAM);
void UpdateMenu(HWND, HMENU);
BOOL InsertListViewItems(HWND);
void PositionHeader(HWND);
/**************************************************************************
Global Variables
**************************************************************************/
HANDLE g_hInst;
TCHAR g_szClassName[] = TEXT("VListVwClass");
#define ITEM_COUNT 100000
/******************************************************************************
WinMain
******************************************************************************/
int PASCAL WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
g_hInst = hInstance;
if(!hPrevInstance)
if(!InitApplication(hInstance))
return FALSE;
//required to use the common controls
InitCommonControls();
/* Perform initializations that apply to a specific instance */
if (!InitInstance(hInstance, nCmdShow))
return FALSE;
/* Acquire and dispatch messages until a WM_QUIT uMessage is received. */
while(GetMessage( &msg, NULL, 0x00, 0x00))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
/******************************************************************************
InitApplication
******************************************************************************/
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
ATOM aReturn;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = (WNDPROC)MainWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN_MENU);
wcex.lpszClassName = g_szClassName;
wcex.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_MAINICON));
wcex.hIconSm = LoadImage(g_hInst, MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 16, 16, 0);
aReturn = RegisterClassEx(&wcex);
if(0 == aReturn)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_MAINICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN_MENU);
wc.lpszClassName = g_szClassName;
aReturn = RegisterClass(&wc);
}
return aReturn;
}
/******************************************************************************
InitInstance
******************************************************************************/
BOOL InitInstance( HINSTANCE hInstance,
int nCmdShow)
{
HWND hWnd;
TCHAR szTitle[MAX_PATH] = "";
g_hInst = hInstance;
LoadString(g_hInst, IDS_APPTITLE, szTitle, sizeof(szTitle));
/* Create a main window for this application instance. */
hWnd = CreateWindowEx( 0,
g_szClassName,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
/* If window could not be created, return "failure" */
if (!hWnd)
return FALSE;
/* Make the window visible; update its client area; and return "success" */
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
/******************************************************************************
MainWndProc
******************************************************************************/
LRESULT CALLBACK MainWndProc( HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
static HWND hwndListView;
switch (uMessage)
{
case WM_CREATE:
// create the TreeView control
hwndListView = CreateListView(g_hInst, hWnd);
//initialize the TreeView control
InitListView(hwndListView);
break;
case WM_NOTIFY:
return ListViewNotify(hWnd, lParam);
case WM_SIZE:
ResizeListView(hwndListView, hWnd);
break;
case WM_INITMENUPOPUP:
UpdateMenu(hwndListView, GetMenu(hWnd));
break;
case WM_CONTEXTMENU:
if(DoContextMenu(hWnd, wParam, lParam))
return FALSE;
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDM_LARGE_ICONS:
SwitchView(hwndListView, LVS_ICON);
break;
case IDM_SMALL_ICONS:
SwitchView(hwndListView, LVS_SMALLICON);
break;
case IDM_LIST:
SwitchView(hwndListView, LVS_LIST);
break;
case IDM_REPORT:
SwitchView(hwndListView, LVS_REPORT);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_ABOUT:
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
/******************************************************************************
AboutDlgProc
******************************************************************************/
BOOL CALLBACK AboutDlgProc( HWND hDlg,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
switch (uMessage)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
EndDialog(hDlg, IDOK);
break;
case IDCANCEL:
EndDialog(hDlg, IDOK);
break;
}
return TRUE;
}
return FALSE;
}
/******************************************************************************
CreateListView
******************************************************************************/
HWND CreateListView(HINSTANCE hInstance, HWND hwndParent)
{
DWORD dwStyle;
HWND hwndListView;
HIMAGELIST himlSmall;
HIMAGELIST himlLarge;
BOOL bSuccess = TRUE;
dwStyle = WS_TABSTOP |
WS_CHILD |
WS_BORDER |
WS_VISIBLE |
LVS_AUTOARRANGE |
LVS_REPORT |
LVS_OWNERDATA;
hwndListView = CreateWindowEx( WS_EX_CLIENTEDGE, // ex style
WC_LISTVIEW, // class name - defined in commctrl.h
"", // dummy text
dwStyle, // style
0, // x position
0, // y position
0, // width
0, // height
hwndParent, // parent
(HMENU)ID_LISTVIEW, // ID
g_hInst, // instance
NULL); // no extra data
if(!hwndListView)
return NULL;
ResizeListView(hwndListView, hwndParent);
//set the image lists
himlSmall = ImageList_Create(16, 16, ILC_COLORDDB | ILC_MASK, 1, 0);
himlLarge = ImageList_Create(32, 32, ILC_COLORDDB | ILC_MASK, 1, 0);
if (himlSmall && himlLarge)
{
HICON hIcon;
//set up the small image list
hIcon = LoadImage(g_hInst, MAKEINTRESOURCE(IDI_DISK), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
ImageList_AddIcon(himlSmall, hIcon);
//set up the large image list
hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_DISK));
ImageList_AddIcon(himlLarge, hIcon);
ListView_SetImageList(hwndListView, himlSmall, LVSIL_SMALL);
ListView_SetImageList(hwndListView, himlLarge, LVSIL_NORMAL);
}
return hwndListView;
}
/******************************************************************************
ResizeListView
******************************************************************************/
void ResizeListView(HWND hwndListView, HWND hwndParent)
{
RECT rc;
GetClientRect(hwndParent, &rc);
MoveWindow( hwndListView,
rc.left,
rc.top,
rc.right - rc.left,
rc.bottom - rc.top,
TRUE);
//only call this if we want the LVS_NOSCROLL style
//PositionHeader(hwndListView);
}
/******************************************************************************
PositionHeader
this needs to be called when the ListView is created, resized, the view is
changed or a WM_SYSPARAMETERCHANGE message is recieved
******************************************************************************/
void PositionHeader(HWND hwndListView)
{
HWND hwndHeader = GetWindow(hwndListView, GW_CHILD);
DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
/*To ensure that the first item will be visible, create the control without
the LVS_NOSCROLL style and then add it here*/
dwStyle |= LVS_NOSCROLL;
SetWindowLong(hwndListView, GWL_STYLE, dwStyle);
//only do this if we are in report view and were able to get the header hWnd
if(((dwStyle & LVS_TYPEMASK) == LVS_REPORT) && hwndHeader)
{
RECT rc;
HD_LAYOUT hdLayout;
WINDOWPOS wpos;
GetClientRect(hwndListView, &rc);
hdLayout.prc = &rc;
hdLayout.pwpos = &wpos;
Header_Layout(hwndHeader, &hdLayout);
SetWindowPos( hwndHeader,
wpos.hwndInsertAfter,
wpos.x,
wpos.y,
wpos.cx,
wpos.cy,
wpos.flags | SWP_SHOWWINDOW);
ListView_EnsureVisible(hwndListView, 0, FALSE);
}
}
/******************************************************************************
InitListView
******************************************************************************/
BOOL InitListView(HWND hwndListView)
{
LV_COLUMN lvColumn;
int i;
TCHAR szString[5][20] = {"Main Column", "Column 1", "Column 2", "Column 3", "Column 4"};
//empty the list
ListView_DeleteAllItems(hwndListView);
//initialize the columns
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 120;
for(i = 0; i < 5; i++)
{
lvColumn.pszText = szString[i];
ListView_InsertColumn(hwndListView, i, &lvColumn);
}
InsertListViewItems(hwndListView);
return TRUE;
}
/******************************************************************************
InsertListViewItems
******************************************************************************/
BOOL InsertListViewItems(HWND hwndListView)
{
//empty the list
ListView_DeleteAllItems(hwndListView);
//set the number of items in the list
ListView_SetItemCount(hwndListView, ITEM_COUNT);
return TRUE;
}
/**************************************************************************
ListViewNotify()
**************************************************************************/
LRESULT ListViewNotify(HWND hWnd, LPARAM lParam)
{
LPNMHDR lpnmh = (LPNMHDR) lParam;
HWND hwndListView = GetDlgItem(hWnd, ID_LISTVIEW);
switch(lpnmh->code)
{
case LVN_GETDISPINFO:
{
LV_DISPINFO *lpdi = (LV_DISPINFO *)lParam;
TCHAR szString[MAX_PATH];
if(lpdi->item.iSubItem)
{
if(lpdi->item.mask & LVIF_TEXT)
{
wsprintf(szString, "Item %d - Column %d", lpdi->item.iItem + 1, lpdi->item.iSubItem);
lstrcpy(lpdi->item.pszText, szString);
}
}
else
{
if(lpdi->item.mask & LVIF_TEXT)
{
wsprintf(szString, "Item %d", lpdi->item.iItem + 1);
lstrcpy(lpdi->item.pszText, szString);
}
if(lpdi->item.mask & LVIF_IMAGE)
{
lpdi->item.iImage = 0;
}
}
}
return 0;
case LVN_ODCACHEHINT:
{
LPNMLVCACHEHINT lpCacheHint = (LPNMLVCACHEHINT)lParam;
/*
This sample doesn't use this notification, but this is sent when the
ListView is about to ask for a range of items. On this notification,
you should load the specified items into your local cache. It is still
possible to get an LVN_GETDISPINFO for an item that has not been cached,
therefore, your application must take into account the chance of this
occurring.
*/
}
return 0;
case LVN_ODFINDITEM:
{
LPNMLVFINDITEM lpFindItem = (LPNMLVFINDITEM)lParam;
/*
This sample doesn't use this notification, but this is sent when the
ListView needs a particular item. Return -1 if the item is not found.
*/
}
return 0;
}
return 0;
}
/**************************************************************************
ErrorHandlerEx()
**************************************************************************/
void ErrorHandlerEx( WORD wLine, LPSTR lpszFile )
{
LPVOID lpvMessage;
DWORD dwError;
char szBuffer[256];
// Allow FormatMessage() to look up the error code returned by GetLastError
dwError = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPTSTR)&lpvMessage,
0,
NULL);
// Check to see if an error occured calling FormatMessage()
if (0 == dwError)
{
wsprintf( szBuffer,
"An error occured calling FormatMessage()."
"Error Code %d",
GetLastError());
MessageBox( NULL,
szBuffer,
"Generic",
MB_ICONSTOP | MB_ICONEXCLAMATION);
return;
}
// Display the error infromation along with the place the error happened.
wsprintf(szBuffer, "Generic, Line=%d, File=%s", wLine, lpszFile);
MessageBox(NULL, lpvMessage, szBuffer, MB_ICONEXCLAMATION | MB_OK);
}
/**************************************************************************
SwitchView()
**************************************************************************/
void SwitchView(HWND hwndListView, DWORD dwView)
{
DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
SetWindowLong(hwndListView, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | dwView);
ResizeListView(hwndListView, GetParent(hwndListView));
}
/**************************************************************************
DoContextMenu()
**************************************************************************/
BOOL DoContextMenu( HWND hWnd,
WPARAM wParam,
LPARAM lParam)
{
HWND hwndListView = (HWND)wParam;
HMENU hMenuLoad,
hMenu;
if(hwndListView != GetDlgItem(hWnd, ID_LISTVIEW))
return FALSE;
hMenuLoad = LoadMenu(g_hInst, MAKEINTRESOURCE(IDM_CONTEXT_MENU));
hMenu = GetSubMenu(hMenuLoad, 0);
UpdateMenu(hwndListView, hMenu);
TrackPopupMenu( hMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
LOWORD(lParam),
HIWORD(lParam),
0,
hWnd,
NULL);
DestroyMenu(hMenuLoad);
return TRUE;
}
/**************************************************************************
UpdateMenu()
**************************************************************************/
void UpdateMenu(HWND hwndListView, HMENU hMenu)
{
UINT uID;
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);
CheckMenuItem(hMenu, IDM_REPORT, MF_BYCOMMAND | MF_UNCHECKED);
//check the appropriate view menu item
dwStyle = GetWindowLong(hwndListView, 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;
case LVS_REPORT:
uID = IDM_REPORT;
break;
}
CheckMenuRadioItem(hMenu, IDM_LARGE_ICONS, IDM_REPORT, uID, MF_BYCOMMAND | MF_CHECKED);
}