Solved

.rc resource file help

Posted on 2004-10-04
13
719 Views
Last Modified: 2013-12-03
Hello,

I am feeling my way round using the windows API and I have a very basic program with a couple of list boxes and a button. I would like to alter the code to use a .rc file so I can use Visual Studio to design the layout of the button and list boxes. Can anyone set me on the right path or give me an example .rc file. The code currently is:

#include <windows.h>

#define ID_LIST2     1
#define ID_LIST1     2
#define ID_BUTTON1   3

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void FillListBox (HWND);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("Environ") ;
     HWND         hwnd ;
      HWND            h_getIDList1;
      HWND            h_getIDList2;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Environment List Box"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     h_getIDList1 = GetDlgItem(hwnd,ID_LIST1);
     FillListBox (h_getIDList1) ;
     
     h_getIDList2 = GetDlgItem(hwnd,ID_LIST2);
     FillListBox (h_getIDList2) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

void FillListBox (HWND hwndList)
{

    TCHAR VarName1[] = TEXT ("Cameron") ;
     TCHAR VarName2[] = TEXT ("Line 2") ;
     SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) VarName1) ;
     SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) VarName2) ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static HWND  hwndList1, hwndList2 ;
     static HWND  hwndButton1;
     int          cxChar, cyChar ;

     switch (message)
     {
     case WM_CREATE :
          cxChar = LOWORD (GetDialogBaseUnits ()) ;
          cyChar = HIWORD (GetDialogBaseUnits ()) ;

               // Create listbox and static text windows.
         
          hwndList1 = CreateWindow (TEXT ("listbox"), NULL,
                              WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER ,
                              cxChar, cyChar * 3,
                              cxChar * 16 + GetSystemMetrics (SM_CXVSCROLL),
                              cyChar * 15,
                              hwnd, (HMENU) ID_LIST1,
                              (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              NULL) ;

          hwndList2 = CreateWindow (TEXT ("listbox"), NULL,
                              WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,
                              cxChar*20, cyChar * 3,
                              cxChar * 16 + GetSystemMetrics (SM_CXVSCROLL),
                              cyChar * 15,
                              hwnd, (HMENU) ID_LIST2,
                              (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              NULL) ;

          hwndButton1 = CreateWindow (TEXT ("Button"), TEXT("Button 1"),
                              WS_CHILD | WS_VISIBLE,
                              cxChar, cyChar * 20,
                              cxChar * 16,
                              cyChar * 2,
                              hwnd, (HMENU) ID_BUTTON1,
                              (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              NULL) ;


          FillListBox (hwndList1) ;
          FillListBox (hwndList2) ;
          return 0 ;
         
     case WM_SETFOCUS :
          SetFocus (hwnd) ;
          return 0 ;

     case WM_DESTROY :
          PostQuitMessage (0) ;
          return 0 ;
         
     case WM_COMMAND:
         if (wParam==ID_BUTTON1)
         SendMessage(hwndList2,LB_ADDSTRING,0,(LPARAM)TEXT("TEXT"));
         return 0;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}
0
Comment
Question by:cweeks
  • 7
  • 6
13 Comments
 
LVL 13

Expert Comment

by:SteH
Comment Utility
Did you hada look at the
CreateDialog
function. There you can specify a dialog resource to use for the dialog. That way you design the dialog in the resource editor of VC++ and use it in your app.

HTH
0
 

Author Comment

by:cweeks
Comment Utility
I think I am going to need it more spood fed than that. I have now created a .rc file to suit my needs but I still have no idea how to tie it into the code I have already. The .rc file is

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef __BORLANDC__
#include "winres.h"
#endif

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
    "#ifndef __BORLANDC__\r\n"
    "#include ""winres.h""\r\n"
    "#endif\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_MAIN DIALOG DISCARDABLE  0, 0, 347, 161
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Controls One"
FONT 8, "MS Sans Serif"
BEGIN
    LISTBOX         IDC_LIST1,154,14,115,126,LBS_NOINTEGRALHEIGHT |
                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
    PUSHBUTTON      "&Add",IDC_BUTTON1,287,30,53,14
    LISTBOX         IDC_LIST2,13,15,110,127,LBS_NOINTEGRALHEIGHT |
                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
    IDD_MAIN, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 340
        VERTGUIDE, 145
        VERTGUIDE, 287
        TOPMARGIN, 7
        BOTTOMMARGIN, 154
    END
END
#endif    // APSTUDIO_INVOKED

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////


0
 
LVL 13

Expert Comment

by:SteH
Comment Utility
This rc file defines a dialog template with the ID IDD_MAIN. (It should exist in resource.h)

This ID you specify in the call to
CreateDialog () via MAKEINTRESOURCE (IDD_MAIN) macro.
See
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/dialogboxreference/dialogboxfunctions/createdialog.asp
for more info on CreateDialog.

The resources (.rc and resource.h) have to be compiled using rc.exe (resource compiler) yielding a .res file. Latter has to be linked to your executable.
0
 

Author Comment

by:cweeks
Comment Utility
Sorry, it's still beyond my grasp.
0
 

Author Comment

by:cweeks
Comment Utility
I have moved on a bit with my understanding. I am now stuck because I think I need to create a window and not a dialog box. The layout I created in the resource editor will be the only window by program has, and to quote Microsoft "A dialog box is a temporary window that contains controls". Obviously this window being my only window shouldn't it be classed as permanent .

I was drawn towards the function CreateWindow but doesn't seem to accept the MAKEINTRESOURCE (IDD_MAIN) macro.
0
 
LVL 13

Expert Comment

by:SteH
Comment Utility
>>The layout I created in the resource editor will be the only window by program has, and to quote Microsoft "A dialog box is a temporary window that contains >>controls". Obviously this window being my only window shouldn't it be classed as permanent .

It depends on what type of application you are going to build. Microsoft offers a Wizard for exe's where one option is a dialog based application. In that case the dialog is the main window and remains until the application ends. The other quote is only true if you have a document interface for your application. There dialogs are used for special user input and displayed only tempoorarily.

So if you want to display a window which contains some controls a dialog as main window is all you need.

Since you have Visual Studio I would like to know why using raw APIs instead of MFC classes. Using the classes limits you to the way they are implemented but releases you from writing all the code yourself. If you want to learn how to use windows in its details go on with the APIs. It will take some time but you get hold of many details. In the case you want to write a simple program and more of your work should go in the design of how the apps works that how to display the layout and how to react to each keytstroke have a look at a class library. One is MFC but others could be used as well.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:cweeks
Comment Utility
I understood MFC to be for C++ only and not C.

The actual purpose of the program is to simulate some embedded code for a small electronic project, and as the compiler for the microcontroller the code will eventually run on is only available in C I wrote the simulation code in C.

The idea of the two listboxes is for debuging output, and the button(s) represent the buttons present on the actualy electronic device.

I have been trying to teach myself from "Prog Win 98 - 5th Ed - Charles Petzold" and "theForger's Win32 API Tutorial at http://winprog.org/tutorial/".

So given your last comments, if I did want to design my program not to use a dialog box and I wanted to use the resource editor to design the window layout, how would I do it ?

And, if I use a dialog box as the main window, why do all the examples I find that have programs solely consisting of dialog boxes not have/need the windows message loop ?

Thanks again.
0
 
LVL 13

Expert Comment

by:SteH
Comment Utility
>>The actual purpose of the program is to simulate some embedded code for a small electronic project, and as the compiler for the microcontroller the code will >>eventually run on is only available in C I wrote the simulation code in C.
OK understood. But why does this effect the graphical front end you are designing? Design the windows application using C++ and call the microcontroller functions from within. Only caveat is that you need to specify for all C functions extern "C" in the header:

extern "C" {
  void MCfunction1 (int);
  void MCfunciton2 (void);
  ...
}

>>So given your last comments, if I did want to design my program not to use a dialog box and I wanted to use the resource editor to design the window layout, how >>would I do it ?
Not creating a dialog you need to create each window indivually. Using a template for this will be not trivial. The resource editor design dialog boxes, using it for other windows will add a lot of complication. See in the link on how to do the DialogProc.

>And, if I use a dialog box as the main window, why do all the examples I find that have programs solely consisting of dialog boxes not have/need the windows >message loop ?
This is most likely because the samples either use MFC where the message loop is hidden from you or because the entire dialog is handled by windows (SaveDialog, etc).
0
 

Author Comment

by:cweeks
Comment Utility
On your second point, I am sure the code below is not MFC, but no message loop, can you explain ?

#include <windows.h>

#include "resource.h"

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
      switch(Message)
      {
            case WM_INITDIALOG:
                  // This is where we set up the dialog box, and initialise any default values

                  SetDlgItemText(hwnd, IDC_TEXT, "This is a string");
                  SetDlgItemInt(hwnd, IDC_NUMBER, 5, FALSE);
            break;
            case WM_COMMAND:
                  switch(LOWORD(wParam))
                  {
                        case IDC_ADD:
                        {
                              // When somebody clicks the Add button, first we get the number of
                              // they entered

                              BOOL bSuccess;
                              int nTimes = GetDlgItemInt(hwnd, IDC_NUMBER, &bSuccess, FALSE);
                              if(bSuccess)
                              {
                                    // Then we get the string they entered
                                    // First we need to find out how long it is so that we can
                                    // allocate some memory

                                    int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_TEXT));
                                    if(len > 0)
                                    {
                                          // Now we allocate, and get the string into our buffer

                                          int i;
                                          char* buf;

                                          buf = (char*)GlobalAlloc(GPTR, len + 1);
                                          GetDlgItemText(hwnd, IDC_TEXT, buf, len + 1);

                                          // Now we add the string to the list box however many times
                                          // the user asked us to.

                                          for(i = 0;i < nTimes; i++)
                                          {
                                                int index = SendDlgItemMessage(hwnd, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)buf);

                                                // Here we are associating the value nTimes with the item
                                                // just for the heck of it, we'll use it to display later.
                                                // Normally you would put some more useful data here, such
                                                // as a pointer.
                                                SendDlgItemMessage(hwnd, IDC_LIST, LB_SETITEMDATA, (WPARAM)index, (LPARAM)nTimes);
                                          }

                                          // Dont' forget to free the memory!
                                          GlobalFree((HANDLE)buf);
                                    }
                                    else
                                    {
                                          MessageBox(hwnd, "You didn't enter anything!", "Warning", MB_OK);
                                    }
                              }
                              else
                              {
                                    MessageBox(hwnd, "Couldn't translate that number :(", "Warning", MB_OK);
                              }

                        }
                        break;
                        case IDC_REMOVE:
                        {
                              // When the user clicks the Remove button, we first get the number
                              // of selected items

                              HWND hList = GetDlgItem(hwnd, IDC_LIST);
                              int count = SendMessage(hList, LB_GETSELCOUNT, 0, 0);
                              if(count != LB_ERR)
                              {
                                    if(count != 0)
                                    {
                                          // And then allocate room to store the list of selected items.

                                          int i;
                                          int *buf = GlobalAlloc(GPTR, sizeof(int) * count);
                                          SendMessage(hList, LB_GETSELITEMS, (WPARAM)count, (LPARAM)buf);
                                          
                                          // Now we loop through the list and remove each item that was
                                          // selected.  

                                          // WARNING!!!  
                                          // We loop backwards, because if we removed items
                                          // from top to bottom, it would change the indexes of the other
                                          // items!!!

                                          for(i = count - 1; i >= 0; i--)
                                          {
                                                SendMessage(hList, LB_DELETESTRING, (WPARAM)buf[i], 0);
                                          }

                                          GlobalFree(buf);
                                    }
                                    else
                                    {
                                          MessageBox(hwnd, "No items selected.", "Warning", MB_OK);
                                    }
                              }
                              else
                              {
                                    MessageBox(hwnd, "Error counting items :(", "Warning", MB_OK);
                              }
                        }
                        break;
                        case IDC_CLEAR:
                              SendDlgItemMessage(hwnd, IDC_LIST, LB_RESETCONTENT, 0, 0);
                        break;
                        case IDC_LIST:
                              switch(HIWORD(wParam))
                              {
                                    case LBN_SELCHANGE:
                                    {
                                          // Get the number of items selected.

                                          HWND hList = GetDlgItem(hwnd, IDC_LIST);
                                          int count = SendMessage(hList, LB_GETSELCOUNT, 0, 0);
                                          if(count != LB_ERR)
                                          {
                                                // We only want to continue if one and only one item is
                                                // selected.

                                                if(count == 1)
                                                {
                                                      // Since we know ahead of time we're only getting one
                                                      // index, there's no need to allocate an array.

                                                      int index;
                                                      int err = SendMessage(hList, LB_GETSELITEMS, (WPARAM)1, (LPARAM)&index);
                                                      if(err != LB_ERR)
                                                      {
                                                            // Get the data we associated with the item above
                                                            // (the number of times it was added)

                                                            int data = SendMessage(hList, LB_GETITEMDATA, (WPARAM)index, 0);

                                                            SetDlgItemInt(hwnd, IDC_SHOWCOUNT, data, FALSE);
                                                      }
                                                      else
                                                      {
                                                            MessageBox(hwnd, "Error getting selected item :(", "Warning", MB_OK);
                                                      }
                                                }
                                                else
                                                {
                                                      // No items selected, or more than one
                                                      // Either way, we aren't going to process this.
                                                      SetDlgItemText(hwnd, IDC_SHOWCOUNT, "-");
                                                }
                                          }
                                          else
                                          {
                                                MessageBox(hwnd, "Error counting items :(", "Warning", MB_OK);
                                          }
                                    }
                                    break;
                              }
                        break;
                  }
            break;
            case WM_CLOSE:
                  EndDialog(hwnd, 0);
            break;
            default:
                  return FALSE;
      }
      return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
      LPSTR lpCmdLine, int nCmdShow)
{
      return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc);
}
0
 
LVL 13

Expert Comment

by:SteH
Comment Utility
The "message loop" is the function DlgProc. Compare it to your message loop above: it contains mainly a big switch statement
switch (message) {
...
}
A dialog will receive only a subset of the messages. They are first tested if they are dialog messages and only then forwarded to the dialog. Otherwise windows will handle them on its own. This behaviour is the same under MFC which only encapsulates the windows API from the programmer.
0
 

Author Comment

by:cweeks
Comment Utility
So what happens then if I have a larger program, and I want one main window that can open several different dialog windows. Can the main windows be a dialog window, and is that acceptable etiquette  ?
0
 
LVL 13

Accepted Solution

by:
SteH earned 250 total points
Comment Utility
Yes. Any application can open additional dialogs. What determines whether to use a dialog or a document/view skeleton is mainly how (or if) data needs to be handled/stored. But this applies more to MFC applications: when using only windows APIs the difference between a dialog based app and a formview (dialog in document/view architecture) is that latter needs more coding for you. From the fact that you have a window with some controls on it in mind for your GUI strongly suggests to use a dialog based appliacation.
0
 

Author Comment

by:cweeks
Comment Utility
Many many thanks for the tolerance and all the help, dialogs it is.

Cam..
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now