Home

List-Based Resources

 

Menus

 

Introduction

A menu is a list of commands that allow the user to interact with an application. To use one of the commands, the user accesses the list and clicks the desired item. There are two main types of menus. On most applications, a menu is represented in the top section with a series of words such as File, Edit, Help. Each of these words represents a category of items. To use this type of menu, the use can display one of the categories (using the mouse or the keyboard). A list would display and the user can select one of the items. The second type of menu is called context sensitive. To use this type of menu, the user typically right-clicks a certain area of the application, a list comes up and the user can select one of the items from the list.

 

Practical Learning Practical Learning: Introducing List-Based Resources

  1. Create a new Win32 Project named Resources2 and create it as an empty project
  2. On the main menu, click Project -> Add Resource...
  3. Double-click Icon and design it as follows (make sure you add the 16x16 version)
     
    32 x 32 16 x 16
  4. Change the ID of the icon to IDI_RESFUND2 and its File Name to resfund2.ico
  5. Create a source file and name it Exercise
  6. From what we have learned so far, type the following code in the file:
    //---------------------------------------------------------------------------
    #include <windows.h>
    #include "resource.h"
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
    			      WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine, int nCmdShow)
    {
    	MSG        Msg;
    	HWND       hWnd;
    	WNDCLASSEX WndClsEx;
            LPCTSTR ClsName = L"ResFund";
       	LPCTSTR WndName = L"Resources Fundamentals";
    
    	// Create the application window
    	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
    	WndClsEx.lpfnWndProc   = WndProcedure;
    	WndClsEx.cbClsExtra    = 0;
    	WndClsEx.cbWndExtra    = 0;
    	WndClsEx.hIcon         = LoadIcon(hInstance,
    					  MAKEINTRESOURCE(IDI_RESFUND2));
    	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	WndClsEx.lpszMenuName  = NULL;
    	WndClsEx.lpszClassName = ClsName;
    	WndClsEx.hInstance     = hInstance;
    	WndClsEx.hIconSm       = LoadIcon(hInstance,
    					  MAKEINTRESOURCE(IDI_RESFUND2));
    
    	// Register the application
    	RegisterClassEx(&WndClsEx);
    
    	// Create the window object
    	hWnd = CreateWindowEx(0,
                              ClsName,
                              WndName,
                   			  WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT,
                   			  CW_USEDEFAULT,
                              CW_USEDEFAULT,
                   			  CW_USEDEFAULT,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);
    	
    	// Find out if the window was created
    	if( !hWnd ) // If the window was not created,
    		return FALSE; // stop the application
    
    	// Display the window to the user
    	ShowWindow(hWnd, nCmdShow);// SW_SHOWNORMAL);
    	UpdateWindow(hWnd);
    
    	// Decode and treat the messages
    	// as long as the application is running
    	while( GetMessage(&Msg, NULL, 0, 0) )
    	{
                 TranslateMessage(&Msg);
                 DispatchMessage(&Msg);
    	}
    
    //	return Msg.wParam;
        return 0;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
    			   WPARAM wParam, LPARAM lParam)
    {
        switch(Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(WM_QUIT);
            break;
        default:
            // Process the left-over messages
            return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
        // If something was not done, let it go
        return 0;
    }
    //---------------------------------------------------------------------------
  7. Execute the application to test it
 
 

Menu Creation

A menu is one of the text-based resources. It is created directly in the rc file. As with other resources, the process of creating a menu depends on the environment you are using. If you are using Borland C++ Builder, you can open your rc file and manually create your menu.

If you are using Microsoft Visual C++, you can use the built-in menu editor. In this case, the actual text that defines and describes the menu would be automatically added to the rc file.

Practical Learning Practical Learning: Creating a Menu

  1. On the main menu, click Project -> Add Resource...
  2. In the Insert Resource dialog box, click Menu and click New
  3. While the first menu item is selected, type &File
  4. Click the next empty item under File. Type &New
  5. In the Properties window, click the ID edit box, type IDM_FILE_NEW and press Enter
  6. Click the next empty item under New and type &Open
  7. In the Properties window, click the ID edit box, type IDM_FILE_OPEN and press Tab
  8. Click the next empty item under Open and type -
  9. Click the next empty item under the new separator and type E&xit
  10. In the Properties window, click the ID edit box, type IDM_FILE_EXIT and press Tab. In the Caption edit box, press Enter
  11. Click the next empty item on the right side of File. Type &Help
  12. Click the next empty item under Help and type &About
  13. In the Properties window, click the ID edit box, type IDM_HELP_ABOUT and press Tab. In the Caption edit box, and press Enter
  14. In the ResourceView tab of the Workspace, under the Menu node, click IDR_MENU1. In the Menu Properties window, change the ID to IDR_MAINFRAME
  15. Open the Exercise.cpp source file and change the lpszMenuName member of the WndClsEx variable as follows:
     
    WndClsEx.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINFRAME);
  16. To test the application, press Ctrl + F5 and press Enter
     
    Resources Fundamentals
  17. Return to your programming environment
 

String Tables

 

Introduction

As its name indicates, a string table is a list of strings created in the resource file. Like the menu resource, the string table is created directly in the resource file. The advantage of using a string table is that the string defined in it are declared globally, meaning that they can be accessed by any object of the application without being declared

 

String Table Creation

As mentioned already, a string table is created in the rc file. Therefore, in Borland C++ Builder and other environments, the list can be manually entered in the resource file. In Visual C++, to create the list, you can add the String Table from the Add Resource dialog box. This opens a special window in which you can edit each string.

Besides new strings you create in the list with their own new identifiers, you can also use the string table to assign strings to already created identifiers. For example, to can assign a string to some or all of the menu items we created earlier.

After creating a string table, you can access any of its strings from anywhere in the application. To access a string, call the LoadString() function.

Practical Learning Practical Learning: Creating and Using a String Table

  1. To create a string table, on the main menu, click Project -> Add Resource...
  2. In the Add Resource dialog box, double-click String Table
  3. Replace the first IDS_ identifier with IDS_APP_NAME and press Tab twice
  4. Type the string as Fundamentals of Windows Resources and press Enter
  5. In the same way, create the following strings and their identifiers (let the string table add the Values):
     
    Value
    IDM_ARROW 105 No tool selected
    IDM_DRAW_LINE 106 Selects the Line tool\nLine
    IDM_DRAW_RECTANGLE 107 Selects the Rectangle tool\nRectangle
    IDM_DRAW_ELLIPSE 108 Selects the Ellipse tool\nEllipse
  6. To assign to an existing identifier, click the arrow of the second identifier and select IDM_FILE_NEW
  7. Click its corresponding Caption section and type Creates a new file\nNew
  8. To use a string from the string table, change the source file as follows:
    //---------------------------------------------------------------------------
    #include <windows.h>
    #include "resource.h"
    
    //---------------------------------------------------------------------------
    char AppCaption[40];
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
    			      WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine, int nCmdShow)
    {
    	MSG        Msg;
    	HWND       hWnd;
    	WNDCLASSEX WndClsEx;
    	LPCTSTR ClsName = L"ResFund";
    
    	LoadString(hInstance, IDS_APP_NAME, AppCaption, 40);
    
    	// Create the application window
    	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
    	WndClsEx.lpfnWndProc   = WndProcedure;
    	WndClsEx.cbClsExtra    = 0;
    	WndClsEx.cbWndExtra    = 0;
    	WndClsEx.hIcon         = LoadIcon(hInstance,
    				 MAKEINTRESOURCE(IDI_RESFUND2));
    	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	WndClsEx.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINFRAME);
    	WndClsEx.lpszClassName = ClsName;
    	WndClsEx.hInstance     = hInstance;
    	WndClsEx.hIconSm       = LoadIcon(hInstance,
    					  MAKEINTRESOURCE(IDI_RESFUND2));
    
    	// Register the application
    	RegisterClassEx(&WndClsEx);
    
    	// Create the window object
    	hWnd = CreateWindowEx(0,
                                  ClsName,
                                  AppCaption,
                    	      WS_OVERLAPPEDWINDOW,
                                  CW_USEDEFAULT,
                                  CW_USEDEFAULT,
                                  CW_USEDEFAULT,
                                  CW_USEDEFAULT,
                                  NULL,
                                  NULL,
                                  hInstance,
                                  NULL);
    	
    	// Find out if the window was created
    	if( !hWnd ) // If the window was not created,
    		return FALSE; // stop the application
    
    	// Display the window to the user
    	ShowWindow(hWnd, nCmdShow);// SW_SHOWNORMAL);
    	UpdateWindow(hWnd);
    
    	// Decode and treat the messages
    	// as long as the application is running
    	while( GetMessage(&Msg, NULL, 0, 0) )
    	{
                 TranslateMessage(&Msg);
                 DispatchMessage(&Msg);
    	}
    
    //	return Msg.wParam;
        return 0;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
    			   WPARAM wParam, LPARAM lParam)
    {
        switch(Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(WM_QUIT);
            break;
        default:
            // Process the left-over messages
            return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
        // If something was not done, let it go
        return 0;
    }
    //---------------------------------------------------------------------------
  9. Execute the application

Toolbars

 

Introduction

A toolbar is an object used to let the user perform actions on an application. Like the menu, the toolbar provides a list of commands. While a menu may require various actions to get to the desired command, a toolbar presents buttons that would lead to the same actions as the menu, only faster. As such, a toolbar is mainly made of buttons placed on it, but a toolbar can also contain many other types of controls.

Toolbar Creation

A toolbar is primarily made of buttons that each displays a small icon, typically 16x16. If you intend to create this type of toolbar, you can start by creating one or more pictures. There are two main types of pictures you would use. The first type uses a kind of picture called a bitmap (we will learn about bitmaps in future lessons). You can create a long picture resource that has a height of 16 pixels (a toolbar can also be taller than that but this height is the most common). Then, add a factor of 16 pixels width for each desired button. This means that, if the toolbar will have one button, you can create a bitmap of 16x16 pixels. If the toolbar will have 4 buttons, you can create a bitmap of height = 16pixels and width = 16 * 4 = 64pixels. After creating this type of bitmap, save it and give it an identifier. The other type of toolbar can use icons that each is created on its own.

Like most other objects you will use in your applications, a toolbar should have an identifier. This would help you and Windows identifier the toolbar.

Since a toolbar is made of small buttons, each button is an object of type TBBUTTON. The TBBUTTON structure is defined as follows:

typedef struct _TBBUTTON {
    int         iBitmap; 
    int         idCommand; 
    BYTE     fsState; 
    BYTE     fsStyle; 
#ifdef _WIN64
    BYTE     bReserved[6]     // padding for alignment
#elif defined(_WIN32)
    BYTE     bReserved[2]     // padding for alignment
#endif
    DWORD_PTR   dwData; 
    INT_PTR          iString; 
} TBBUTTON, NEAR *PTBBUTTON *LPTBBUTTON;

The buttons are stored in an array of TBBUTTON values.

Unlike the other resources we have used so far, to add a toolbar to your application, you must programmatically create it. To do this, call either the CreateWindowEx or the CreateToolbarEx() function. The syntax of the CreateToolbarEx() function is:

HWND CreateToolbarEx(HWND hwnd,
    		     DWORD ws,
    		     UINT wID,
    		     int nBitmaps,
    		     HINSTANCE hBMInst,
    		     UINT_PTR wBMID,
    		     LPCTBBUTTON lpButtons,
    		     int iNumButtons,
    		     int dxButton,
    		     int dyButton,
    		     int dxBitmap,
    		     int dyBitmap,
    		     UINT uStructSize
);

The first argument is the window that serves as the parent to the toolbar. This is usually the first window you would have created.

The second argument specifies the style used to display the toolbar. This parameter is a combination of windows styles and toolbar styles.

The third argument is the identifier of the toolbar.

The nBitmaps is used to specify the number of pictures included in the bitmap you will use

The hBMInst is the application that will manage the toolbar

The hBMID is an identifier of the bitmap

The lpButtons argument is a pointer to the array of TBBUTTON values you have defined already.

The iNumButtons specifies the number of buttons that will be created on the toolbar

The dxButton and dyButton parameters represent the dimension of each button

The dxBitmap and dyBitmap parameters represent the dimension of the bitmap that will be used on the buttons

The last argument is the size of the TBBUTTON structure.

The functions and classes (actually, structures) used to create and manage a toolbar are defined in the commctrl.h header file. The commctrl.h header is part of the comctl32.lib library. This library is not carried by the windows.h header or its associated libraries. Therefore, since the toolbar belongs to the family of Common Controls, you must explicitly add the comctl32.lib library whenever you want to use one of them.

Practical Learning Practical Learning: Creating a Toolbar

  1. To include the comctl32.lib library in your application, on the main menu, click Project -> Add Existing Item...
  2. Locate the folder that contains your libraries and display it in the Look In combo box. For Visual C++ 6.0, this would be in Drive:\Program Files\Microsoft Visual Studio\VC98\Lib
     

     
    For Visual C++ .NET, this would be Drive:\Program Files\Microsoft Visual Studio .NET 2003\VC7\PlatformSDK\Lib
     
     
  3. Click ComCtl32.Lib
     
    Add Existing Item
  4. Click Open
  5. To start a toolbar, on the main menu, click Project -> Add Resources and double-click Bitmap
  6. Design the bitmap as 96 x 16 (width x height) as follows:
     
    Bitmap Design
  7. Change its ID to IDB_STANDARD and its file name to standard.bmp
  8. To add the toolbar to the application, change the source file as follows:
    //---------------------------------------------------------------------------
    #include <windows.h>
    #include <commctrl.h>
    #include "resource.h"
    
    //---------------------------------------------------------------------------
    char AppCaption[40];
    HINSTANCE hInst;
    const int NUMBUTTONS = 7;
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
    			      WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine, int nCmdShow)
    {
    	MSG        Msg;
    	HWND       hWnd;
    	WNDCLASSEX WndClsEx;
        LPCTSTR ClsName = L"ResFund";
    
    	LoadString(hInstance, IDS_APP_NAME, AppCaption, 40);
    
    	hInst = hInstance;
    
    	// Create the application window
    	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
    	WndClsEx.lpfnWndProc   = WndProcedure;
    	WndClsEx.cbClsExtra    = 0;
    	WndClsEx.cbWndExtra    = 0;
    	WndClsEx.hIcon         = LoadIcon(hInstance,
    					  MAKEINTRESOURCE(IDI_RESFUND2));
    	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	WndClsEx.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINFRAME);
    	WndClsEx.lpszClassName = ClsName;
    	WndClsEx.hInstance     = hInst;
    	WndClsEx.hIconSm       = LoadIcon(hInstance,
    					  MAKEINTRESOURCE(IDI_RESFUND2));
    
    	// Register the application
    	RegisterClassEx(&WndClsEx);
    
    	// Create the window object
    	hWnd = CreateWindowEx(0,
                              ClsName,
                              AppCaption,
                   		  WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT,
                   		  CW_USEDEFAULT,
                              CW_USEDEFAULT,
                   		  CW_USEDEFAULT,
                              NULL,
                              NULL,
                              hInstance,
                              NULL);
    	
    	// Find out if the window was created
    	if( !hWnd ) // If the window was not created,
    		return FALSE; // stop the application
    
    	INITCOMMONCONTROLSEX InitCtrlEx;
    
    	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    	InitCtrlEx.dwICC  = ICC_BAR_CLASSES;
    	InitCommonControlsEx(&InitCtrlEx);
    
    	TBBUTTON tbrButtons[7];
    	
    	tbrButtons[0].iBitmap   = 0;
    	tbrButtons[0].idCommand = IDM_FILE_NEW;
    	tbrButtons[0].fsState   = TBSTATE_ENABLED;
    	tbrButtons[0].fsStyle   = TBSTYLE_BUTTON;
    	tbrButtons[0].dwData    = 0L;
    	tbrButtons[0].iBitmap   = 0;
    	tbrButtons[0].iString   = 0;
    	
    	tbrButtons[1].iBitmap   = 1;
    	tbrButtons[1].idCommand = IDM_FILE_OPEN;
    	tbrButtons[1].fsState   = TBSTATE_ENABLED;
    	tbrButtons[1].fsStyle   = TBSTYLE_BUTTON;
    	tbrButtons[1].dwData    = 0L;
    	tbrButtons[1].iString   = 0;
    
    	tbrButtons[2].iBitmap   = 0;
    	tbrButtons[2].idCommand = 0;
    	tbrButtons[2].fsState   = TBSTATE_ENABLED;
    	tbrButtons[2].fsStyle   = TBSTYLE_SEP;
    	tbrButtons[2].dwData    = 0L;
    	tbrButtons[2].iString   = 0;
    
    	tbrButtons[3].iBitmap   = 2;
    	tbrButtons[3].idCommand = IDM_ARROW;
    	tbrButtons[3].fsState   = TBSTATE_ENABLED;
    	tbrButtons[3].fsStyle   = TBSTYLE_BUTTON;
    	tbrButtons[3].dwData    = 0L;
    	tbrButtons[3].iString   = 0;
    
    	tbrButtons[4].iBitmap   = 3;
    	tbrButtons[4].idCommand = IDM_DRAW_LINE;
    	tbrButtons[4].fsState   = TBSTATE_ENABLED;
    	tbrButtons[4].fsStyle   = TBSTYLE_BUTTON;
    	tbrButtons[4].dwData    = 0L;
    	tbrButtons[4].iString   = 0;
    
    	tbrButtons[5].iBitmap   = 4;
    	tbrButtons[5].idCommand = IDM_DRAW_RECTANGLE;
    	tbrButtons[5].fsState   = TBSTATE_ENABLED;
    	tbrButtons[5].fsStyle   = TBSTYLE_BUTTON;
    	tbrButtons[5].dwData    = 0L;
    	tbrButtons[5].iString   = 0;
    	
    	tbrButtons[6].iBitmap   = 5;
    	tbrButtons[6].idCommand = IDM_DRAW_ELLIPSE;
    	tbrButtons[6].fsState   = TBSTATE_ENABLED;
    	tbrButtons[6].fsStyle   = TBSTYLE_BUTTON;
    	tbrButtons[6].dwData    = 0L;
    	tbrButtons[6].iString   = 0;
    
    	HWND hWndToolbar;
    	hWndToolbar = CreateToolbarEx(hWnd,
    		                      WS_VISIBLE | WS_CHILD | WS_BORDER,
    	                              IDB_STANDARD,
    	                              NUMBUTTONS,
    				      hInst,
    			              IDB_STANDARD,
    				      tbrButtons,
    				      NUMBUTTONS,
    				      16, 16, 16, 16,
    				      sizeof(TBBUTTON));
    
    	// Display the window to the user
    	ShowWindow(hWnd, nCmdShow);
    	UpdateWindow(hWnd);
    
    	// Decode and treat the messages
    	// as long as the application is running
    	while( GetMessage(&Msg, NULL, 0, 0) )
    	{
                 TranslateMessage(&Msg);
                 DispatchMessage(&Msg);
    	}
    
        return 0;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
    			   WPARAM wParam, LPARAM lParam)
    {
        switch(Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(WM_QUIT);
            break;
        default:
            // Process the left-over messages
            return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
        // If something was not done, let it go
        return 0;
    }
    //---------------------------------------------------------------------------
  9. Execute the application:
     
    Fundamentals of Windows Resources
  10. Return to your programming environment
 

Previous Copyright © 2004-2010 FunctionX, Inc. Next