home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / commctrl / vlistvw / vlistvw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-28  |  18.2 KB  |  665 lines

  1. /**************************************************************************
  2.    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3.    ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4.    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5.    PARTICULAR PURPOSE.
  6.  
  7.    Copyright 1997 Microsoft Corporation.  All Rights Reserved.
  8. **************************************************************************/
  9.  
  10. /**************************************************************************
  11.    Include Files
  12. **************************************************************************/
  13.  
  14. #define STRICT
  15.  
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include <commctrl.h>
  19. #include "VListVw.h"
  20.  
  21. /**************************************************************************
  22.    Local Function Prototypes
  23. **************************************************************************/
  24.  
  25. #define ErrorHandler() ErrorHandlerEx(__LINE__, __FILE__)
  26. void ErrorHandlerEx(WORD, LPSTR);
  27.  
  28. LRESULT ListViewNotify(HWND, LPARAM);
  29. void SwitchView(HWND, DWORD);
  30. BOOL DoContextMenu(HWND, WPARAM, LPARAM);
  31. void UpdateMenu(HWND, HMENU);
  32. BOOL InsertListViewItems(HWND);
  33. void PositionHeader(HWND);
  34.  
  35. /**************************************************************************
  36.    Global Variables
  37. **************************************************************************/
  38.  
  39. HANDLE   g_hInst;
  40. TCHAR    g_szClassName[] = TEXT("VListVwClass");
  41.  
  42. #define ITEM_COUNT   100000
  43.  
  44. /******************************************************************************
  45.  
  46.    WinMain
  47.  
  48. ******************************************************************************/
  49.  
  50. int PASCAL WinMain(  HINSTANCE hInstance,
  51.                      HINSTANCE hPrevInstance,
  52.                      LPSTR lpCmdLine,
  53.                      int nCmdShow)
  54. {
  55. MSG  msg;
  56.  
  57. g_hInst = hInstance;
  58.  
  59. if(!hPrevInstance)
  60.    if(!InitApplication(hInstance))
  61.       return FALSE;
  62.  
  63. //required to use the common controls
  64. InitCommonControls();
  65.  
  66. /* Perform initializations that apply to a specific instance */
  67.  
  68. if (!InitInstance(hInstance, nCmdShow))
  69.    return FALSE;
  70.  
  71. /* Acquire and dispatch messages until a WM_QUIT uMessage is received. */
  72.  
  73. while(GetMessage( &msg, NULL, 0x00, 0x00))
  74.    {
  75.    TranslateMessage(&msg);
  76.    DispatchMessage(&msg);
  77.    }
  78.  
  79. return msg.wParam;
  80. }
  81.  
  82.  
  83. /******************************************************************************
  84.  
  85.    InitApplication
  86.  
  87. ******************************************************************************/
  88.  
  89. BOOL InitApplication(HINSTANCE hInstance)
  90. {
  91. WNDCLASSEX  wcex;
  92. ATOM        aReturn;
  93.  
  94. wcex.cbSize          = sizeof(WNDCLASSEX);
  95. wcex.style           = 0;
  96. wcex.lpfnWndProc     = (WNDPROC)MainWndProc;
  97. wcex.cbClsExtra      = 0;
  98. wcex.cbWndExtra      = 0;
  99. wcex.hInstance       = hInstance;
  100. wcex.hCursor         = LoadCursor(NULL, IDC_ARROW);
  101. wcex.hbrBackground   = (HBRUSH)(COLOR_WINDOW + 1);
  102. wcex.lpszMenuName    = MAKEINTRESOURCE(IDM_MAIN_MENU);
  103. wcex.lpszClassName   = g_szClassName;
  104. wcex.hIcon           = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_MAINICON));
  105. wcex.hIconSm         = LoadImage(g_hInst, MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 16, 16, 0);
  106.  
  107. aReturn = RegisterClassEx(&wcex);
  108.  
  109. if(0 == aReturn)
  110.    {
  111.    WNDCLASS wc;
  112.  
  113.    wc.style          = 0;
  114.    wc.lpfnWndProc    = (WNDPROC)MainWndProc;
  115.    wc.cbClsExtra     = 0;
  116.    wc.cbWndExtra     = 0;
  117.    wc.hInstance      = hInstance;
  118.    wc.hIcon          = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_MAINICON));
  119.    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  120.    wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  121.    wc.lpszMenuName   = MAKEINTRESOURCE(IDM_MAIN_MENU);
  122.    wc.lpszClassName  = g_szClassName;
  123.  
  124.    aReturn = RegisterClass(&wc);
  125.    }
  126.  
  127. return aReturn;
  128. }
  129.  
  130.  
  131. /******************************************************************************
  132.  
  133.    InitInstance
  134.  
  135. ******************************************************************************/
  136.  
  137. BOOL InitInstance(   HINSTANCE hInstance,
  138.                      int nCmdShow)
  139. {
  140. HWND     hWnd;
  141. TCHAR    szTitle[MAX_PATH] = "";
  142.  
  143. g_hInst = hInstance;
  144.  
  145. LoadString(g_hInst, IDS_APPTITLE, szTitle, sizeof(szTitle));
  146.  
  147. /* Create a main window for this application instance.  */
  148. hWnd = CreateWindowEx(  0,
  149.                         g_szClassName,
  150.                         szTitle,
  151.                         WS_OVERLAPPEDWINDOW,
  152.                         CW_USEDEFAULT,
  153.                         CW_USEDEFAULT,
  154.                         CW_USEDEFAULT,
  155.                         CW_USEDEFAULT,
  156.                         NULL,
  157.                         NULL,
  158.                         hInstance,
  159.                         NULL);
  160.  
  161. /* If window could not be created, return "failure" */
  162.  
  163. if (!hWnd)
  164.    return FALSE;
  165.  
  166. /* Make the window visible; update its client area; and return "success" */
  167.  
  168. ShowWindow(hWnd, nCmdShow);
  169. UpdateWindow(hWnd);
  170. return TRUE;
  171.  
  172. }
  173.  
  174. /******************************************************************************
  175.  
  176.    MainWndProc
  177.  
  178. ******************************************************************************/
  179.  
  180. LRESULT CALLBACK MainWndProc( HWND hWnd,
  181.                               UINT uMessage,
  182.                               WPARAM wParam,
  183.                               LPARAM lParam)
  184. {
  185. static HWND hwndListView;
  186.  
  187. switch (uMessage)
  188.    {
  189.    case WM_CREATE:
  190.       // create the TreeView control
  191.       hwndListView = CreateListView(g_hInst, hWnd);
  192.       
  193.       //initialize the TreeView control
  194.       InitListView(hwndListView);
  195.       
  196.       break;
  197.  
  198.    case WM_NOTIFY:
  199.       return ListViewNotify(hWnd, lParam);
  200.    
  201.    case WM_SIZE:
  202.       ResizeListView(hwndListView, hWnd);
  203.       break;
  204.  
  205.    case WM_INITMENUPOPUP:
  206.       UpdateMenu(hwndListView, GetMenu(hWnd));
  207.       break;
  208.    
  209.    case WM_CONTEXTMENU:
  210.       if(DoContextMenu(hWnd, wParam, lParam))
  211.          return FALSE;
  212.       break;
  213.    
  214.    case WM_COMMAND:
  215.       switch (GET_WM_COMMAND_ID(wParam, lParam))
  216.          {
  217.          case IDM_LARGE_ICONS:
  218.             SwitchView(hwndListView, LVS_ICON);
  219.             break;
  220.          
  221.          case IDM_SMALL_ICONS:
  222.             SwitchView(hwndListView, LVS_SMALLICON);
  223.             break;
  224.          
  225.          case IDM_LIST:
  226.             SwitchView(hwndListView, LVS_LIST);
  227.             break;
  228.          
  229.          case IDM_REPORT:
  230.             SwitchView(hwndListView, LVS_REPORT);
  231.             break;
  232.          
  233.          case IDM_EXIT:
  234.             DestroyWindow(hWnd);
  235.             break;
  236.          
  237.          case IDM_ABOUT:
  238.             DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc);
  239.             break;   
  240.  
  241.          }
  242.       break;
  243.  
  244.    case WM_DESTROY:
  245.       PostQuitMessage(0);
  246.       break;
  247.  
  248.    default:
  249.       break;
  250.    }
  251. return DefWindowProc(hWnd, uMessage, wParam, lParam);
  252. }
  253.  
  254.  
  255. /******************************************************************************
  256.  
  257.    AboutDlgProc
  258.  
  259. ******************************************************************************/
  260.  
  261. BOOL CALLBACK AboutDlgProc(   HWND hDlg, 
  262.                               UINT uMessage, 
  263.                               WPARAM wParam, 
  264.                               LPARAM lParam)
  265. {
  266. switch (uMessage)
  267.    {
  268.    case WM_INITDIALOG:
  269.       return TRUE;
  270.       
  271.    case WM_COMMAND:
  272.       switch(wParam)
  273.          {
  274.          case IDOK:
  275.             EndDialog(hDlg, IDOK);
  276.             break;
  277.  
  278.          case IDCANCEL:
  279.             EndDialog(hDlg, IDOK);
  280.             break;
  281.          }
  282.       return TRUE;
  283.     } 
  284.     
  285. return FALSE;
  286. }
  287.  
  288. /******************************************************************************
  289.  
  290.    CreateListView
  291.  
  292. ******************************************************************************/
  293.  
  294. HWND CreateListView(HINSTANCE hInstance, HWND hwndParent)
  295. {
  296. DWORD       dwStyle;
  297. HWND        hwndListView;
  298. HIMAGELIST  himlSmall;
  299. HIMAGELIST  himlLarge;
  300. BOOL        bSuccess = TRUE;
  301.  
  302. dwStyle =   WS_TABSTOP | 
  303.             WS_CHILD | 
  304.             WS_BORDER | 
  305.             WS_VISIBLE |
  306.             LVS_AUTOARRANGE |
  307.             LVS_REPORT | 
  308.             LVS_OWNERDATA;
  309.             
  310. hwndListView = CreateWindowEx(   WS_EX_CLIENTEDGE,          // ex style
  311.                                  WC_LISTVIEW,               // class name - defined in commctrl.h
  312.                                  "",                        // dummy text
  313.                                  dwStyle,                   // style
  314.                                  0,                         // x position
  315.                                  0,                         // y position
  316.                                  0,                         // width
  317.                                  0,                         // height
  318.                                  hwndParent,                // parent
  319.                                  (HMENU)ID_LISTVIEW,        // ID
  320.                                  g_hInst,                   // instance
  321.                                  NULL);                     // no extra data
  322.  
  323. if(!hwndListView)
  324.    return NULL;
  325.  
  326. ResizeListView(hwndListView, hwndParent);
  327.  
  328. //set the image lists
  329. himlSmall = ImageList_Create(16, 16, ILC_COLORDDB | ILC_MASK, 1, 0);
  330. himlLarge = ImageList_Create(32, 32, ILC_COLORDDB | ILC_MASK, 1, 0);
  331.  
  332. if (himlSmall && himlLarge)
  333.    {
  334.    HICON hIcon;
  335.  
  336.    //set up the small image list
  337.    hIcon = LoadImage(g_hInst, MAKEINTRESOURCE(IDI_DISK), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  338.    ImageList_AddIcon(himlSmall, hIcon);
  339.  
  340.    //set up the large image list
  341.    hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_DISK));
  342.    ImageList_AddIcon(himlLarge, hIcon);
  343.  
  344.    ListView_SetImageList(hwndListView, himlSmall, LVSIL_SMALL);
  345.    ListView_SetImageList(hwndListView, himlLarge, LVSIL_NORMAL);
  346.    }
  347.  
  348. return hwndListView;
  349. }
  350.  
  351. /******************************************************************************
  352.  
  353.    ResizeListView
  354.  
  355. ******************************************************************************/
  356.  
  357. void ResizeListView(HWND hwndListView, HWND hwndParent)
  358. {
  359. RECT  rc;
  360.  
  361. GetClientRect(hwndParent, &rc);
  362.  
  363. MoveWindow( hwndListView, 
  364.             rc.left,
  365.             rc.top,
  366.             rc.right - rc.left,
  367.             rc.bottom - rc.top,
  368.             TRUE);
  369.  
  370. //only call this if we want the LVS_NOSCROLL style
  371. //PositionHeader(hwndListView);
  372. }
  373.  
  374. /******************************************************************************
  375.  
  376.    PositionHeader
  377.  
  378.    this needs to be called when the ListView is created, resized, the view is 
  379.    changed or a WM_SYSPARAMETERCHANGE message is recieved
  380.  
  381. ******************************************************************************/
  382.  
  383. void PositionHeader(HWND hwndListView)
  384. {
  385. HWND  hwndHeader = GetWindow(hwndListView, GW_CHILD);
  386. DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
  387.  
  388. /*To ensure that the first item will be visible, create the control without 
  389. the LVS_NOSCROLL style and then add it here*/
  390. dwStyle |= LVS_NOSCROLL;
  391. SetWindowLong(hwndListView, GWL_STYLE, dwStyle);
  392.  
  393. //only do this if we are in report view and were able to get the header hWnd
  394. if(((dwStyle & LVS_TYPEMASK) == LVS_REPORT) && hwndHeader)
  395.    {
  396.    RECT        rc;
  397.    HD_LAYOUT   hdLayout;
  398.    WINDOWPOS   wpos;
  399.  
  400.    GetClientRect(hwndListView, &rc);
  401.    hdLayout.prc = &rc;
  402.    hdLayout.pwpos = &wpos;
  403.  
  404.    Header_Layout(hwndHeader, &hdLayout);
  405.  
  406.    SetWindowPos(  hwndHeader, 
  407.                   wpos.hwndInsertAfter, 
  408.                   wpos.x, 
  409.                   wpos.y,
  410.                   wpos.cx, 
  411.                   wpos.cy, 
  412.                   wpos.flags | SWP_SHOWWINDOW);
  413.  
  414.    ListView_EnsureVisible(hwndListView, 0, FALSE);
  415.    }
  416. }
  417.  
  418. /******************************************************************************
  419.  
  420.    InitListView
  421.  
  422. ******************************************************************************/
  423.  
  424. BOOL InitListView(HWND hwndListView)
  425. {
  426. LV_COLUMN   lvColumn;
  427. int         i;
  428. TCHAR       szString[5][20] = {"Main Column", "Column 1", "Column 2", "Column 3", "Column 4"};
  429.  
  430. //empty the list
  431. ListView_DeleteAllItems(hwndListView);
  432.  
  433. //initialize the columns
  434. lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  435. lvColumn.fmt = LVCFMT_LEFT;
  436. lvColumn.cx = 120;
  437. for(i = 0; i < 5; i++)
  438.    {
  439.    lvColumn.pszText = szString[i];
  440.    ListView_InsertColumn(hwndListView, i, &lvColumn);
  441.    }
  442.  
  443. InsertListViewItems(hwndListView);
  444.  
  445. return TRUE;
  446. }
  447.  
  448. /******************************************************************************
  449.  
  450.    InsertListViewItems
  451.  
  452. ******************************************************************************/
  453.  
  454. BOOL InsertListViewItems(HWND hwndListView)
  455. {
  456. //empty the list
  457. ListView_DeleteAllItems(hwndListView);
  458.  
  459. //set the number of items in the list
  460. ListView_SetItemCount(hwndListView, ITEM_COUNT);
  461.  
  462. return TRUE;
  463. }
  464.  
  465. /**************************************************************************
  466.  
  467.    ListViewNotify()
  468.  
  469. **************************************************************************/
  470.  
  471. LRESULT ListViewNotify(HWND hWnd, LPARAM lParam)
  472. {
  473. LPNMHDR  lpnmh = (LPNMHDR) lParam;
  474. HWND     hwndListView = GetDlgItem(hWnd, ID_LISTVIEW);
  475.  
  476. switch(lpnmh->code)
  477.    {
  478.    case LVN_GETDISPINFO:
  479.       {
  480.       LV_DISPINFO *lpdi = (LV_DISPINFO *)lParam;
  481.       TCHAR szString[MAX_PATH];
  482.  
  483.       if(lpdi->item.iSubItem)
  484.          {
  485.          if(lpdi->item.mask & LVIF_TEXT)
  486.             {
  487.             wsprintf(szString, "Item %d - Column %d", lpdi->item.iItem + 1, lpdi->item.iSubItem);
  488.             lstrcpy(lpdi->item.pszText, szString);
  489.             }
  490.          }
  491.       else
  492.          {
  493.          if(lpdi->item.mask & LVIF_TEXT)
  494.             {
  495.             wsprintf(szString, "Item %d", lpdi->item.iItem + 1);
  496.             lstrcpy(lpdi->item.pszText, szString);
  497.             }
  498.  
  499.          if(lpdi->item.mask & LVIF_IMAGE)
  500.             {
  501.             lpdi->item.iImage = 0;
  502.             }
  503.          }
  504.       }
  505.       return 0;
  506.  
  507.    case LVN_ODCACHEHINT:
  508.       {
  509.       LPNMLVCACHEHINT   lpCacheHint = (LPNMLVCACHEHINT)lParam;
  510.       /*
  511.       This sample doesn't use this notification, but this is sent when the 
  512.       ListView is about to ask for a range of items. On this notification, 
  513.       you should load the specified items into your local cache. It is still 
  514.       possible to get an LVN_GETDISPINFO for an item that has not been cached, 
  515.       therefore, your application must take into account the chance of this 
  516.       occurring.
  517.       */
  518.       }
  519.       return 0;
  520.  
  521.    case LVN_ODFINDITEM:
  522.       {
  523.       LPNMLVFINDITEM lpFindItem = (LPNMLVFINDITEM)lParam;
  524.       /*
  525.       This sample doesn't use this notification, but this is sent when the 
  526.       ListView needs a particular item. Return -1 if the item is not found.
  527.       */
  528.       }
  529.       return 0;
  530.    }
  531.  
  532. return 0;
  533. }
  534.  
  535. /**************************************************************************
  536.  
  537.    ErrorHandlerEx()
  538.  
  539. **************************************************************************/
  540.  
  541. void ErrorHandlerEx( WORD wLine, LPSTR lpszFile )
  542. {
  543. LPVOID lpvMessage;
  544. DWORD  dwError;
  545. char szBuffer[256];
  546.  
  547. // Allow FormatMessage() to look up the error code returned by GetLastError
  548. dwError = FormatMessage(   FORMAT_MESSAGE_ALLOCATE_BUFFER | 
  549.                               FORMAT_MESSAGE_FROM_SYSTEM, 
  550.                            NULL, 
  551.                            GetLastError(), 
  552.                            MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 
  553.                            (LPTSTR)&lpvMessage, 
  554.                            0, 
  555.                            NULL);
  556.  
  557. // Check to see if an error occured calling FormatMessage()
  558. if (0 == dwError)
  559.    {
  560.    wsprintf(   szBuffer, 
  561.                "An error occured calling FormatMessage()."
  562.                "Error Code %d", 
  563.                GetLastError());
  564.    MessageBox( NULL, 
  565.                szBuffer, 
  566.                "Generic", 
  567.                MB_ICONSTOP | MB_ICONEXCLAMATION);
  568.    return;
  569.    }
  570.  
  571. // Display the error infromation along with the place the error happened.
  572. wsprintf(szBuffer, "Generic, Line=%d, File=%s", wLine, lpszFile);
  573. MessageBox(NULL, lpvMessage, szBuffer, MB_ICONEXCLAMATION | MB_OK);
  574. }
  575.  
  576. /**************************************************************************
  577.  
  578.    SwitchView()
  579.  
  580. **************************************************************************/
  581.  
  582. void SwitchView(HWND hwndListView, DWORD dwView)
  583. {
  584. DWORD dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
  585.  
  586. SetWindowLong(hwndListView, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | dwView);
  587. ResizeListView(hwndListView, GetParent(hwndListView));
  588. }
  589.  
  590. /**************************************************************************
  591.  
  592.    DoContextMenu()
  593.  
  594. **************************************************************************/
  595.  
  596. BOOL DoContextMenu(  HWND hWnd, 
  597.                      WPARAM wParam, 
  598.                      LPARAM lParam)
  599. {
  600. HWND  hwndListView = (HWND)wParam;
  601. HMENU hMenuLoad,
  602.       hMenu;
  603.  
  604. if(hwndListView != GetDlgItem(hWnd, ID_LISTVIEW))
  605.    return FALSE;
  606.  
  607. hMenuLoad = LoadMenu(g_hInst, MAKEINTRESOURCE(IDM_CONTEXT_MENU));
  608. hMenu = GetSubMenu(hMenuLoad, 0);
  609.  
  610. UpdateMenu(hwndListView, hMenu);
  611.  
  612. TrackPopupMenu(   hMenu,
  613.                   TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  614.                   LOWORD(lParam),
  615.                   HIWORD(lParam),
  616.                   0,
  617.                   hWnd,
  618.                   NULL);
  619.  
  620. DestroyMenu(hMenuLoad);
  621.  
  622. return TRUE;
  623. }
  624.  
  625. /**************************************************************************
  626.  
  627.    UpdateMenu()
  628.  
  629. **************************************************************************/
  630.  
  631. void UpdateMenu(HWND hwndListView, HMENU hMenu)
  632. {
  633. UINT  uID;
  634. DWORD dwStyle;
  635.  
  636. //uncheck all of these guys
  637. CheckMenuItem(hMenu, IDM_LARGE_ICONS,  MF_BYCOMMAND | MF_UNCHECKED);
  638. CheckMenuItem(hMenu, IDM_SMALL_ICONS,  MF_BYCOMMAND | MF_UNCHECKED);
  639. CheckMenuItem(hMenu, IDM_LIST,  MF_BYCOMMAND | MF_UNCHECKED);
  640. CheckMenuItem(hMenu, IDM_REPORT,  MF_BYCOMMAND | MF_UNCHECKED);
  641.  
  642. //check the appropriate view menu item
  643. dwStyle = GetWindowLong(hwndListView, GWL_STYLE);
  644. switch(dwStyle & LVS_TYPEMASK)
  645.    {
  646.    case LVS_ICON:
  647.       uID = IDM_LARGE_ICONS;
  648.       break;
  649.       
  650.    case LVS_SMALLICON:
  651.       uID = IDM_SMALL_ICONS;
  652.       break;
  653.       
  654.    case LVS_LIST:
  655.       uID = IDM_LIST;
  656.       break;
  657.    
  658.    case LVS_REPORT:
  659.       uID = IDM_REPORT;
  660.       break;
  661.    }
  662. CheckMenuRadioItem(hMenu, IDM_LARGE_ICONS, IDM_REPORT, uID,  MF_BYCOMMAND | MF_CHECKED);
  663.  
  664. }
  665.