win32 v. MFC ?

I have always programmed in console apps but want to move into windows programming. I want to know the advantages and disadvantages of win32 and MFC. Which one would people recommend, coming from a C++ console programming background? Or is there an even better windows GUI to ues (Windows Forms?). I want to write small windows programs that will do statistical calculations on data sets.

Also, what books would people recommend or resources (internet or otherwise) that is available? I already have Programming Windows with MFC (Prosise) and Programming Windows (Petzoid).

Thank you in advance!
Last edited on
closed account (E0p9LyTq)
MFC encapsulates much of the Win32 in C++ classes.

Personally I use, and am still learning, both. I prefer Win32, MFC hides far too much of the Windows API IMO.

Which version of Petold's book? 5th or 6th edition? The 5th is straight C/Win32, the 6th is C# and XML. PR6E teaches how to program for Windows much like MFC, hiding far too much of the implementation details. Sadly IMO that is the route MS is going.

If you are really wanting to learn Windows programming I would suggest getting Visual Studio 2015 Community. It is free, and include C++/MFC (have to choose a custom install to get them, though.)

The MFC and 5th Ed Programming Windows books are OOOOOLD, teaching you how to program for Win98. Some of the more advanced programs in PW5E won't run without crashing without changing some code, most will run fine as is.

The Windows GUI is a separate thing from programming statistical calculation on data sets. If you can mash C++ code to do that work, then adapting your code to use a GUI is not all that hard. The hardest idea to overcome is how Windows programs run vs. console programs. Having to share resources like the keyboard and monitor for example.
closed account (E0p9LyTq)
You know what this does:
1
2
3
4
5
6
#include <iostream>

int main()
{
   std::cout << "Hello World!\n";
}


Adding a Win32 GUI requires this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* a minimal Windows API application skeleton */

#include <windows.h>
#include <tchar.h>

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
   const TCHAR szWinClass[] = TEXT("WinSkeleton");
   const TCHAR szAppTitle[] = TEXT("Skeletal Windows API Application");

   HWND       hwnd;
   MSG        msg;
   WNDCLASSEX wc;

   wc.cbSize = sizeof(WNDCLASSEX);
   wc.hInstance     = hInstance;
   wc.lpszClassName = szWinClass;
   wc.lpfnWndProc   = WndProc;
   wc.style         = CS_HREDRAW | CS_VREDRAW;
   wc.hIcon         = (HICON) LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
   wc.hIconSm       = NULL;
   wc.hCursor       = (HCURSOR) LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
   wc.lpszMenuName  = NULL;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 0;
   wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

   if (0 == RegisterClassEx(&wc))
   {
      MessageBox(NULL, TEXT("Couldn't Register the Window Class!"), TEXT("ERROR"), MB_OK | MB_ICONERROR);
      return FALSE;
   }

   hwnd = CreateWindow(szWinClass, szAppTitle,
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       NULL, NULL, hInstance, NULL);

   if (NULL == hwnd)
   {
      MessageBox(NULL, TEXT("Couldn't Create the Main Window!"), TEXT("ERROR"), MB_OK | MB_ICONERROR);
      return FALSE;
   }

   ShowWindow(hwnd, nShowCmd);
   UpdateWindow(hwnd);

   while (GetMessage(&msg, NULL, 0, 0) != 0)
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   return (int) msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   HDC         hdc;
   PAINTSTRUCT ps;
   RECT        rect;
   TCHAR       test[] = TEXT("Hello World! From a Windows App!");

   switch (message)
   {
   case WM_PAINT:
      hdc = BeginPaint(hwnd, &ps);
      GetClientRect(hwnd, &rect);
      DrawText(hdc, test, -1, &rect, DT_SINGLELINE | DT_NOCLIP | DT_CENTER | DT_VCENTER);
      EndPaint(hwnd, &ps);
      return 0;

   case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
   }

   return DefWindowProc(hwnd, message, wParam, lParam);
}


The MFC method:
MFC.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// MFC.h : main header file for the MFC application
//
#pragma once

// derive the necessary classes

// this is the application class
class CTheApp : public CWinApp
{
public:
   virtual BOOL InitInstance();
};


class CMainWnd : public CFrameWnd
{
public:
   CMainWnd();

protected:
   afx_msg void OnPaint();
   DECLARE_MESSAGE_MAP()
};

extern CTheApp  theApp;


MFC.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// MFC.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "MFC.h"

// instantiate the application
CTheApp  theApp;


// initialize the application
BOOL CTheApp::InitInstance()
{
   m_pMainWnd = new CMainWnd;

   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();

   return TRUE;
}


// construct the main window
CMainWnd::CMainWnd()
{
   Create(NULL, _T("The MFC Hello Application"));
}


// the application's message map
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
   ON_WM_PAINT()
END_MESSAGE_MAP()


void CMainWnd::OnPaint()
{
   CPaintDC dc(this);

   CRect rect;
   GetClientRect(&rect);

   dc.DrawText(_T("Hello, MFC!!!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
Last edited on
FurryGuy:

I have the 6th Ed. which is C# and XLM. Yes, I'm trying to figure out if it is worth the time and effort to learn C# if that is the way the industry is going. Any suggestions?

Thanks for the suggestion of Visual Studio 2015 Community! I'll get it right away.

I guess I'll give up reading Prosise (1999) for now if it is that outdated.
FurryGuy:

Regarding your code to display "hello world." I've figured out how to add an option to the file menu. I originally included FILE and EDIT only on the file menu bar. I then added ANALYZE, which I want to call my own C++ function to do some analysis on a data set. Specifically, how do I link the C++ function to the ANALYZE menu option so that if it is chosen it will run my function? Can you show how in both MFC and win35? Thanks in advance!
closed account (E0p9LyTq)
I didn't say the MFC 2nd Edition book (as well as Petzold's 5th edition) is OUTDATED, I merely said it is OLD. MFC hasn't changed all that much. The Win32 API hasn't changed a lot either. There have been additions and extensions, such as GDI+ and DirectX.

I posted the code examples simply to show how Win32 API programming differs from MFC, and how really different GUI programming is from C++. "Adding a GUI" is not as easy as writing a couple of lines of new code. The way a program interacts with a user is entirely different.

Both books explain far better than I could how to deal with menus.
I want to write small windows programs that will do statistical calculations on data sets.

Since you have a book about C# and XAML why don't you give it a try? It's easier to learn than WinApi and MFC. A nice side effect is that you can build apps for all the stores(Windows, Apple and Android) if you might wish in the future.
In FurryGuy's code you see where a "Window Class" (that's a foundational concept) is Registered with RegisterClassEx(), and an instance of the main program window created with CreateWindowEx(). Once the window is created Windows the operating system will communicate events to window instances through the Window Procedure (another foundational concept). In the case of menus, or more generally, "child window controls" (yet one more foundational topic), e.g., buttons, text boxes, menus, etc., those are also windows, but whose Window Procedures are within Windows itself rather than in your application. They communicate with your application by sending messages to it which translate into Window Procedure calls in your app. Specifically, if you've successfully created a menu in FurryGuy's app above, you will have an associated child window control id (menu id) associated with it which you provided however you create the menu whether it be through a "resource script" or with Api code. When you click that menu it will send a WM_COMMAND message to the Window Procedure and the low order Word of the wParam parameter to the Window Procedure will contain the menu/child window id of the item you interacted with in some way, i.e., clicking it or whatever.

One thing the other excellent responders to this question didn't address is dependencies. With Win32/64 your program has no dependencies other than that it be executed on a functioning Windows operating system. There are no support files whatsoever required to be associated with it if you give/sell it to others. With any other choice the dependencies are massive.

I can understand your desire to learn to create GUIs instead of console mode programs, but for your needs as stated console mode programs would serve you fine.
Last edited on
@freddie,

One thing the other excellent responders to this question didn't address is dependencies. With Win32/64 your program has no dependencies other than that it be executed on a functioning Windows operating system. There are no support files whatsoever required to be associated with it if you give/sell it to others. With any other choice the dependencies are massive.

What dependencies do you mean? .NET is included since Windows 7
I don't really keep up with .NET much Thomas as I don't use it. But in the past there were always dependencies due to the different versions. And as far as I know it was included as part of an operating system install as far back as Win XP, at least some specific version of it, which wouldn't necessarily match the one a developer was using. Has that changed all of a sudden? I'm asking because I don't know. If I develop a .NET app on a Windows 10 machine can I just give the small executable to someone running a Windows 7, Vista, or XP machine without any setup packages and expect it to work?
If I develop a .NET app on a Windows 10 machine can I just give the small executable to someone running a Windows 7, Vista, or XP machine without any setup packages and expect it to work?

I don't remember which version of .NET was installed by default.
If you use the latest version other computers might have not the right version.
If you use the VS to create an installer the installer will offer to download the required version. The .NET runtime is around 50 MB.
Thank you all for your informative and excellent responses! I know how to associate a button with a handler so that a function is called. I'm trying to figure out how to do the same with a menu option. I know I will figure it out eventually, but any help is greatly appreciated and would save me a lot of wasted time and effort.
Last edited on

I know how to associate a button with a handler so that a function is called. I'm trying to figure out how to do the same with a menu option.


Its exactly the same nesmith as with a button. You have a Control ID with a button and you have a Menu ID with a menu, and associated with the WM_COMMAND message the LOWORD(wParam) will identify the menu selection executed. Perhaps you are having difficulties setting up your resource files?
closed account (E0p9LyTq)
Win32 menu application:

resource definitions (resource.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef __RESOURCES_H__
#define __RESOURCES_H__ 

// main menu identifier ========================================================
#define IDR_MENU    10001

// main menu menu-items identifiers ============================================
#define IDM_EXIT    20001
#define IDM_HELP    20002

#define IDM_ALPHA   20101
#define IDM_BETA    20102
#define IDM_GAMMA   20103
#define IDM_DELTA   20104
#define IDM_EPSILON 20105
#define IDM_ZETA    20106
#define IDM_ETA     20107
#define IDM_THETA   20108

// accelerator table identifier ------------------------------------------------
#define IDR_ACCEL   30001

#endif 


resource script (WinMenu.rc):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <windows.h>
#include "resources.h"

// main menu resources =========================================================
TheMenu MENU
{
   POPUP "&One"
   {
      MENUITEM "&Alpha\tF2",    IDM_ALPHA
      MENUITEM "&Beta\tF3",     IDM_BETA
      MENUITEM "E&xit\tCtrl+X", IDM_EXIT
   }

   POPUP "&Two"
   {
      MENUITEM "&Gamma\tShift+G", IDM_GAMMA

      POPUP "&Delta"
      {
         MENUITEM "&Epsilon\tCtrl+E", IDM_EPSILON
         MENUITEM "&Zeta\tCtrl+Z",    IDM_ZETA
      }

      MENUITEM "&Eta\tF5",        IDM_ETA
      MENUITEM "&Theta\tCtrl+F5", IDM_THETA
   }

   POPUP "&Help"
   {
      MENUITEM "&About....\tF1", IDM_HELP
   }
}


// accelerator table resources =================================================
TheAccels ACCELERATORS
{
   "^X",   IDM_EXIT,    VIRTKEY
   VK_F1,  IDM_HELP,    VIRTKEY

   VK_F2,  IDM_ALPHA,   VIRTKEY
   VK_F3,  IDM_BETA,    VIRTKEY
   "G",    IDM_GAMMA,   VIRTKEY, SHIFT
   "^E",   IDM_EPSILON, VIRTKEY
   "Z",    IDM_ZETA,    VIRTKEY, CONTROL
   VK_F5,  IDM_ETA,     VIRTKEY
   VK_F5,  IDM_THETA,   VIRTKEY, CONTROL
}


Windows menu source (WinMenu.cpp):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include "resources.h"

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nShowCmd)
{
   UNREFERENCED_PARAMETER(lpCmdLine);

   const TCHAR szWinClass[] = TEXT("Menu Accelerators");
   const TCHAR szAppTitle[] = TEXT("Using Menus with Accelerators");
   BOOL        bReturn;
   HWND        hwnd;
   MSG         msg;
   WNDCLASSEX  wc;

   // a handle to an accelerator table
   HACCEL      hAccel;

   wc.cbSize        = sizeof(WNDCLASSEX);
   wc.hInstance     = hInstance;
   wc.lpszClassName = szWinClass;
   wc.lpfnWndProc   = WndProc;
   wc.style         = CS_HREDRAW | CS_VREDRAW;
   wc.hIcon         = (HICON) LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
   wc.hIconSm       = NULL;
   wc.hCursor       = (HCURSOR) LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
   wc.lpszMenuName  = TEXT("TheMenu");
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 0;
   wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

   if (0 == RegisterClassEx(&wc))
   {
      MessageBox(NULL, TEXT("Couldn't Register the Window Class!"), TEXT("ERROR"), MB_OK | MB_ICONERROR);
      return FALSE;
   }

   hwnd = CreateWindow(szWinClass, szAppTitle, WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, CW_USEDEFAULT,
                       NULL, NULL, hInstance, NULL);

   if (NULL == hwnd)
   {
      MessageBox(NULL, TEXT("Couldn't Create the Main Window!"), TEXT("ERROR"), MB_OK | MB_ICONERROR);
      return FALSE;
   }

   // load the accelerator resources in the accelerator table
   hAccel = LoadAccelerators(hInstance, TEXT("TheAccels"));

   ShowWindow(hwnd, nShowCmd);
   UpdateWindow(hwnd);

   while ((bReturn = GetMessage(&msg, NULL, 0, 0) != 0) && bReturn != -1)
   {
      // determine if the message is an accelerator command
      // if not process the message as normal
      if (TranslateAccelerator(hwnd, hAccel, &msg) == 0)
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
   }

   return (int) msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch(message)
   {
   case WM_COMMAND:
      switch (LOWORD(wParam))
      {
      case IDM_EXIT:
         PostMessage(hwnd, WM_CLOSE, wParam, lParam);
         return 0;

      case IDM_HELP:
         MessageBox(hwnd, TEXT("Using Menus with Accelerators"), TEXT("About...."), MB_OK);
         return 0;

      case IDM_ALPHA:
         MessageBox(hwnd, TEXT("Alpha"), TEXT("Alpha"), MB_OK);
         return 0;

      case IDM_BETA:
         MessageBox(hwnd, TEXT("Beta"), TEXT("Beta"), MB_OK);
         return 0;

      case IDM_GAMMA:
         MessageBox(hwnd, TEXT("Gamma"), TEXT("Gamma"), MB_OK);
         return 0;

      case IDM_EPSILON:
         MessageBox(hwnd, TEXT("Epsilon"), TEXT("Epsilon"), MB_OK);
         return 0;

      case IDM_ZETA:
         MessageBox(hwnd, TEXT("Zeta"), TEXT("Zeta"), MB_OK);
         return 0;

      case IDM_ETA:
         MessageBox(hwnd, TEXT("Eta"), TEXT("Eta"), MB_OK);
         return 0;

      case IDM_THETA:
         MessageBox(hwnd, TEXT("Theta"), TEXT("Theta"), MB_OK);
         return 0;
      }

      break;

   case WM_CLOSE:
      if (MessageBox(hwnd, TEXT("Quit the Program?"), TEXT("Exit"), MB_ICONQUESTION | MB_YESNO) == IDYES)
      {
         DestroyWindow(hwnd);
      }
      return 0;

   case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
   }

   return DefWindowProc(hwnd, message, wParam, lParam);
}
closed account (E0p9LyTq)
MFC menu application:

resource definitions (resource.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __RESOURCE_H__
#define __RESORUCE_H__

#define  IDM_HELP       1001

#define  IDM_ALPHA      1101
#define  IDM_BETA       1102
#define  IDM_GAMMA      1103
#define  IDM_DELTA      1104
#define  IDM_EPSILON    1105
#define  IDM_ZETA       1106
#define  IDM_ETA        1107
#define  IDM_THETA      1108

#define  IDM_TIME       1201

#endif 


resource script (MFCMenu.rc):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "AfxRes.h"
#include "resource.h"

TheMenu  MENU
{
   POPUP "&One"
   {
      MENUITEM "&Alpha\tA",               IDM_ALPHA
      MENUITEM "&Beta\tShift+B",          IDM_BETA
   }
   POPUP "&Two"
   {
      MENUITEM "&Gamma\tShift+G",         IDM_GAMMA
      POPUP    "&Delta"
      {
         MENUITEM "&Epsilon\tCtrl+E",     IDM_EPSILON
         MENUITEM SEPARATOR
         MENUITEM "&Zeta\tCtrl+Z",        IDM_ZETA
      }
      MENUITEM "&Eta\tAlt+F2",            IDM_ETA
      MENUITEM "&Theta\tCtrl+Shift+F3",   IDM_THETA
   }
   POPUP "&Help"
   {
      MENUITEM "&About...",               IDM_HELP
   }
}


TheAccels   ACCELERATORS
{
   VK_F1,   IDM_HELP,      VIRTKEY

   "a",     IDM_ALPHA
   "B",     IDM_BETA
   "G",     IDM_GAMMA,     VIRTKEY, SHIFT
   "E",     IDM_EPSILON,   VIRTKEY, CONTROL
   "^Z",    IDM_ZETA
   VK_F2,   IDM_ETA,       VIRTKEY, ALT
   VK_F3,   IDM_THETA,     VIRTKEY, CONTROL, SHIFT

   "T",     IDM_TIME,      VIRTKEY, ALT
}


MFC menu application header (MFCMenu.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef __MFCMENU_H__
#define __MFCMENU_H__

#include <AfxWin.h>

// application class
class CTheApp : public CWinApp
{
protected:
   BOOL InitInstance();
};


// main window class
class CMainWnd : public CFrameWnd
{
public:
   CMainWnd();

protected:
   afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
   afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

protected:
   // define menu handlers
   afx_msg void OnHelp();
   afx_msg void OnAlpha();
   afx_msg void OnBeta();
   afx_msg void OnGamma();
   afx_msg void OnEpsilon();
   afx_msg void OnZeta();
   afx_msg void OnEta();
   afx_msg void OnTheta();

   // define hotkey handler
   afx_msg void OnTime();

protected:
   DECLARE_MESSAGE_MAP()
};

#endif 


MFC menu application source (MFCMenu.cpp):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "MFCMenu.h"
#include "resource.h"

// instantiate the application
CTheApp  theApp;


// initialize the application
BOOL CTheApp::InitInstance()
{
   m_pMainWnd  = new CMainWnd;

   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();
   
   return TRUE;
}


// create the main window
CMainWnd::CMainWnd()
{
   Create(NULL, "Using Menus with Accelerators",
          WS_OVERLAPPEDWINDOW, rectDefault, NULL, "TheMenu");

   if (LoadAccelTable("TheAccels") == FALSE)
   {
      MessageBox("Can't Load Accelerators!", "ERROR");
   }
}


// application's message map
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
   ON_WM_LBUTTONDOWN()
   ON_WM_RBUTTONDOWN()
   ON_COMMAND(IDM_HELP, OnHelp)
   ON_COMMAND(IDM_ALPHA, OnAlpha)
   ON_COMMAND(IDM_BETA, OnBeta)
   ON_COMMAND(IDM_GAMMA, OnGamma)
   ON_COMMAND(IDM_EPSILON, OnEpsilon)
   ON_COMMAND(IDM_ZETA, OnZeta)
   ON_COMMAND(IDM_ETA, OnEta)
   ON_COMMAND(IDM_THETA, OnTheta)
   ON_COMMAND(IDM_TIME, OnTime)
END_MESSAGE_MAP()


// process left mouse button
afx_msg void CMainWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
   int i = MessageBox("Press One", "Left Button", MB_ABORTRETRYIGNORE);

   switch (i)
   {
      case IDABORT:
         MessageBox("", "Abort");
         break;

      case IDRETRY:
         MessageBox("", "Retry");
         break;

      case IDIGNORE:
         MessageBox("", "Ignore");
         break;
   }
}


// process right mouse button
afx_msg void CMainWnd::OnRButtonDown(UINT nFlags, CPoint point)
{
   int i = MessageBox("Press One", "Right Button",
                      MB_ICONHAND | MB_YESNO);

   switch (i)
   {
      case IDYES:
         MessageBox("", "Yes");
         break;

      case IDNO:
         MessageBox("", "NO");
         break;
   }
}


// process IDM_HELP
afx_msg void CMainWnd::OnHelp()
{
   MessageBox("Menu Demo\n(With Accelerators)", "About...");
}


// process IDM_ALPHA
afx_msg void CMainWnd::OnAlpha()
{
   MessageBox("Alpha", "Alpha");
}


// process IDM_BETA
afx_msg void CMainWnd::OnBeta()
{
   MessageBox("Beta", "Beta");
}


// process IDM_GAMMA
afx_msg void CMainWnd::OnGamma()
{
   MessageBox("Gamma", "Gamma");
}


// process IDM_EPSILON
afx_msg void CMainWnd::OnEpsilon()
{
   MessageBox("Epsilon", "Epsilon");
}


// process IDM_ZETA
afx_msg void CMainWnd::OnZeta()
{
   MessageBox("Zeta", "Zeta");
}


// process IDM_ETA
afx_msg void CMainWnd::OnEta()
{
   MessageBox("Eta", "Eta");
}


// process IDM_THETA
afx_msg void CMainWnd::OnTheta()
{
   MessageBox("Theta", "Theta");
}


// process IDM_TIME
afx_msg void CMainWnd::OnTime()
{
   CString str;
   CTime curTime = CTime::GetCurrentTime();

   str = curTime.Format("%a, %b %d, %Y - %I:%M:%S %p");
   
   MessageBox(str, "Time and Date");
}
closed account (E0p9LyTq)
@nesmith,

There is one small error with the MFC menu/accelerator implementation. Can you spot it?

The error is a runtime error, not a compile-time error.
Looks like in the code:

"E", IDM_EPSILON, VIRTKEY, CONTROL

should instead be:

"^E", IDM_EPSILON, VIRTKEY, CONTROL

and / or:

"^Z", IDM_ZETA, VIRTKEY, CONTROL
FurryGuy: Thanks for the code. It will be a big help in getting me on my way!
closed account (E0p9LyTq)
"E", IDM_EPSILON, VIRTKEY, CONTROL and "^E", IDM_EPSILON are the same, CTRL+E.

ACCELERATORS resource (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/aa380610(v=vs.85).aspx

The functional error is with ALT+T, the sole change to the menu/accelerator resources between the WinMenu and MFCMenu examples. The "&Two" popup is over-ridden by the "Time" hot key.
Last edited on
closed account (E0p9LyTq)
nesmith wrote:
Thanks for the code. It will be a big help in getting me on my way!

Merely example code, slightly rewritten, taken from the books you have.
Topic archived. No new replies allowed.