List of available com ports in menu of MFC dialog - c++

I am stuck. I have just a little experience with MFC and inherited a MFC program from a former coworker.
I want to add a list of available com ports in the menu bar, so the user can select whatever he wants. During the further runtime of the program, this menu should be locked.
I already created the Menu and added it to my Dialog. But:
How can I dynamically show the list of available com ports during the initialization?
How can I figure out which Port was selected? Is there something. like a return value?
Actually the second question bugs me the most.
Edit1:
to be more clear: I already know how to get the list of available com ports and currently I am displaying them in a combo box. But I want to do it with a Menu instead.
Edit2: This is what I got so far. Question 1 is solved!
//create a menu object for main menu
CMenu *menu = new CMenu();
menu->CreateMenu();
//another menu object for submenu
CMenu *subMenu = new CMenu();
subMenu->CreateMenu();
//create subsubmenus
CMenu *ComPortSelect = new CMenu();
CMenu *ModeSelect = new CMenu();
ComPortSelect->CreateMenu();
ModeSelect->CreateMenu();
//append available ports (portlist created earlier)
for (INT_PTR i = 0; i < portlist.GetCount(); i++)
{
ComPortSelect->AppendMenu(MF_POPUP, ID_SHOW, portlist[i]);
}
ModeSelect->AppendMenu(MF_POPUP, ID_SHOW, _T("User"));
ModeSelect->AppendMenu(MF_POPUP, ID_SHOW, _T("Expert"));
//append subsubmenu to submenu
subMenu->AppendMenu(MF_POPUP | MF_STRING, (UINT)ComPortSelect->m_hMenu, _T("ComPorts"));
subMenu->AppendMenu(MF_POPUP | MF_STRING, (UINT)ModeSelect->m_hMenu, _T("Mode"));
//append submenu to menu
menu->AppendMenu(MF_POPUP | MF_STRING, (UINT)subMenu->m_hMenu, _T("Advanced"));
SetMenu(menu);

I played with interfacing a program to an Arduino some time ago. Different models of Arduinos that I had used different COM ports so I also had a need to scan for available ports.
I forget the exact ins and outs of it now, but you an use one syntax when opening COM ports upto about 8 or 10 I think, and a different one for any higher numbered ports. Fortunately, the syntax that works for higher numbered ports also works for the lower numbered ones - my code uses the higher-numbered port syntax and works fine for both.
The code I used for a non-mfc win32 project follows:
void initPortCombo(HWND combo)
{
int curPort;
char mPortName[16];
HANDLE hCom;
for (curPort=1; curPort<=20; curPort++)
{
sprintf(mPortName, "\\\\.\\COM%d", curPort);
hCom = CreateFile(mPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (hCom != INVALID_HANDLE_VALUE)
{
sprintf(mPortName, "COM%d", curPort);
CloseHandle(hCom);
SendMessage(combo, CB_ADDSTRING, 0, (LPARAM)mPortName);
}
}
}
As for your second question, when you dynamically add a menu option, you need to specify the ID that the menu item has. So with that in mind, when your WM_COMMAND handler fires, you simply need to reverse the logic you used at the time you added the menu items.
For instance, if you assign the menu items an ID of (4000 + com_port_number), you can subtract 4000 from the ID of the control that fired the WM_COMMAND handler. If this results in a valid number (I guess from 1 to 20 or whatever port number you scan up to) then you know it was the menu item that corresponds to one of your com-ports.
Just have a play with adding dynamic menu items and then determining which one was selected. I dont MFC, so cant help you there.

One way to find the installed COM ports is to call the GetDefaultCommConfig API. There is some sample code for this at http://www.naughter.com/enumser.html
When a menu command is selected by the user you receive a WM_COMMAND message from the menu, with parameters that include the ID of the chosen menu item. You put an ON_COMMAND_RANGE statement in your message map to route these messages to a message handler function.

Related

How to Make a Simple GUI with DropDown Menus with C++

I am really struggling how to make a window with three selections of options. I currently have a setup that uses a CFileDialog object and have successfully implemented two dropdown menus and multiple check items.
What I want is to implement a pop up window that has the two drop down menus and the check boxes. If a certain item is selected in one of the dropdown menus then the file dialog is opened.
Currently I am trying to make a CWnd object and try to write code for it there.
CWnd myWindow;
BOOL VALUE = myWindow.Create(_T("DesktopApp"), _T("test"), WS_VISIBLE | WS_BORDER | WS_CAPTION,
RECT{ 100,100,400,400 },
myWindow.GetDesktopWindow(), 12);
myWindow.ShowWindow(SW_SHOWNORMAL);
if (VALUE == FALSE) {
return 0;
}
Every time I run this, it prematurely returns (VALUE == FALSE). Did I do something wrong? Is there a simpler way to create a window?
The first argument to CWnd::Create is the window class name. A class with the requested name must have been registered before it can be created.
It is common to register an application local class for the application's main window. MFC provides a convenient wrapper function (AfxRegisterWndClass) to register a window class.

C++ - MFC - Change text of a CMenu

Good morning everybody,
I created an application that manages multi-language. When I dynamically change the default language of the application, all the text of the different graphic components change very well excepted one component. I don't know why ?
I tried those lines for modifying the text of the menu title but it changes only if I put my mouse on this menu.
MENUITEMINFO info;
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_ID;
VERIFY(AfxGetMainWnd()->GetMenu()->GetMenuItemInfoA(0, &info, TRUE));
AfxGetMainWnd()->GetMenu()->ModifyMenuA(0, MF_STRING | MF_BYPOSITION, info.wID, theApp.vattingTranslation.GetDescription(256).c_str());
Why does it not refresh automatically my menu item "Système" ?
Thanks in advance
You need to call a DrawMenuBar function afterwards as specified in the ModifyMenu documentation:
The application must call the DrawMenuBar function whenever a menu
changes, whether the menu is in a displayed window.

Disabling (Greying out) multiple GUI Items in C++

Question:
I am looking for an effective way to disable(grey) mutiple items in a MFC C++ application. Depending on if the user is signed into a SQL Server or Oracle account, I wish to disable a section of GUI items.
What I have tried:
I have used the following code to disable one of my two "Create User" buttons.
if(checkIsSQLServer())
{
CWnd *oraCreateUser = GetDlgItem(BTN_ORA_CREATE);
oraCreateUser->EnableWindow(false); //Disable Oracle "Create User" button
}
else
{
CWnd *sqlCreateLogin = GetDlgItem(BTN_SQL_CREATE);
sqlCreateLogin->EnableWindow(false); //Disable SQL Server "Create User" button.
}
.
This code works perfectly, however it only disables the button. I wish to disable all items within either groupbox.
Do I need to create a CWnd* object for every item I wish to disable? Is there a more effective way, such as a way to disable all items that are contained within a group box?
I use this:
void EnableDlgItem (CWnd *dlg, int items[], BOOL bEnable)
{
int i = 0, item ;
while ((item = items[i++]) != 0)
{
CWnd *pControl = dlg->GetDlgItem(item) ;
if (pControl != NULL)
pControl->EnableWindow(bEnable) ;
}
}
...
And in some CYourDialog::OnSomethingFunction()
static int ids[] = {IDOK, IDC_EDIT1, IDC_EDIT2, 0};
EnableDlgItem(this, ids, FALSE);
As others have said, MFC does not expose a method that allows you to enable/disable a group of controls. You'll need to craft your own code to do that.
I was faced with the very same situation and decided to handle it by deriving my own groupbox class. In my situation, the groupbox enable/disable functioning was tied to the state of a checkbox as seen below.
(I've redacted some information from it).
Clicking on the checkbox will toggle the enable/disable of all controls within the groupbox. There's nothing stopping you from deriving your own class for the groupbox and exposing a method that can be called (rather than a checkbox) to enable/disable controls. The advantage to this approach is that if you create the class in a generic manner, you can re-use it in other situations where a groupbox is the "parent" of other controls.

How can I disable and gray the top level menu item using MFC

I have a dialog application in which I want to have clickable menu items at the top of the dialog. These items do not show a drop down menu but actually run the associated commands.
I did this by setting Popup=False in the dialogs properties and assigning a message-id but my problem is not having the ability to disable the item properly when it makes no sense for the item to be clickable (depending on internal state stored in the dialog)
I have already found out how to disable any popup-parent menu items from http://www.microsoft.com/msj/0299/c/c0299.aspx, but this isn't exactly what I want
I have also found out how to add menu command routing to dialogs from the msdn knowledgebase article KB242577.
This works fine for sub-menu items, but not for the top level menu.
I am currently using the following function to do the disabling
void CYourDlg::EnableMenuItem(UINT nCommand, BOOL bEnable)
{
CMenu* pMenu = GetMenu();
pMenu->EnableMenuItem(nCommand, bEnable ? 0 : MF_DISABLED | MF_GRAYED);
}
This half works, if you alt-tab away from the app it does show as disabled, otherwise it doesn't.
Is there a way to invalidate the area programmatically?
I think an non-client area message may be involved.
I have not tried but in regular window (not dialog) CWnd::DrawMenuBar should do what you want. It might work with dialog based applications as well.
void CYourDlg::EnableMenuItem(UINT nCommand, BOOL bEnable)
{
CMenu* pMenu = GetMenu();
pMenu->EnableMenuItem(nCommand, bEnable ? 0 : MF_DISABLED | MF_GRAYED);
DrawMenuBar();
}
I think you should add an ON_UPDATE handler for your menu ID. This would ensure that the menu is enabled/disabled when you want to.

Motif main window w/o system menu, minimize and maximize boxes how? (C++)

How do I create a Motif main window that doesn't have a system menu, minimize and maximize boxes? I just cannot find out how by googling and reading docs and tutorials. I believe that it should be possible with some additional parameters for XtVaCreateManagedWindow, but which?
I have tried several variants of XtVaSetValues (topWid, XmNmwmDecorations, ...) but none worked. Instead I get an error message that I need to use a vendor shell for this. Most widget types aren't derived from vendor shells however, and when I e.g. try to use a dialog shell and put a scrollable text widget inside of it, then then text widget seems to control the dialog.
Apparently it's not (easily) possible to get rid of the window (system) menu, but it seems to be possible to disable window menu items with some code like this:
int i;
XtVaGetValues (widget, XmNmwmFunctions, &i);
i &= ~(MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE);
XtVaSetValues (widget, XmNmwmFunctions, i);
which removes the related window decoration too and apparently even works for non vendor shell widgets.
There should also be the possibility to remove the decorations (i.e. make them invisible). However, please note that these "system menu" decorations belong to the Window Manager, not your Motif program itself. It is up to the Window Manager to handle your requests or disregard them--you might get vendor-specific behavior with any MWM resources.
Anyway, here's the code sample to try out:
int decors; //bit-mask of flags defining the decorations, from Xm/MwmUtil.h
XtVaGetValues(dlg, XmNmwmDecorations, &decors, NULL);
decors &= ~MWM_DECOR_MENU;
decors &= ~MWM_DECOR_MAXIMIZE;
decors &= ~MWM_DECOR_MINIMIZE;
XtVaSetValues(dlg, XmNmwmDecorations, decors, NULL);
If you intend to run your application from Mwm, you can achieve the desired behavior by setting (e.g. via XtVaAppInitialize()) the following X11 resources:
! Title bar buttons
Mwm*YourApplicationClassHere.clientDecoration: -minimize -maximize
! Window menu functions
Mwm*YourApplicationClassHere.clientFunctions: -minimize -maximize
These resources are explained in more detail here and here.
Speaking of window menu, this one depends on a specific window manager in use. Mwm, for instance, allows the client to set the menu name using Mwm*YourApplicationClassHere.windowMenu resource, the menu itself must be defined in either ${HOME}/.mwmrc or global mwmrc, or XmNmwmMenu resource of VendorShell. The resulting custom window menu is exposed as a _MOTIF_WM_MENU atom, which seems to be ignored by modern window managers.
Sample mwmrc menu definitions may look like this
Menu CustomMenu0
{
Restore _R Alt<Key>F5 f.restore
Move _M Alt<Key>F7 f.move
Size _S Alt<Key>F8 f.resize
Minimize _n Alt<Key>F9 f.minimize
Maximize _x Alt<Key>F10 f.maximize
Lower _L Alt<Key>F3 f.lower
no-label f.separator
Pass\ Keys _K f.pass_keys
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
Menu CustomMenu1
{
Your\ Application\ Name\ Here f.title
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
(see the function descriptions). Custom menu items can be added using f.send_msg (examples here and here).
I'm pretty sure all of the above also applies to Dtwm (CDE).