I am working on a Windows application using MFC and Visual Studio C++ 17.
I have multiple tabs in the application, one of which is currently implemented using CListBox and needs to be reimplemented using CCheckListBox.
CCheckListBox is a child class of CListBox.
I have a vector of unique CString's I want to display in the box.
To start simple, I tried making the tab with CListBox and by using CListBox::AddString(), this worked exactly as I wanted it to. It sorted the strings alphabetically, and automatically added a scroll bar on the side when the vector had too many CString's to display all at once in the list.
However, when swapping the CListBox variable to a CCheckListBox variable, I have come across the error when I press run along the lines of:
Debug Assertion Failed! ..... \mfc\winctrl3.cpp Line: 588
I found this GitHub link that has the winctrl3.cpp file and on line 588, there is a function called OnLButtonDblClk which is somewhat explained here.
The trouble is I am unsure of how to swap a variable from a parent class to a child class. Is it so different for Windows classes? In the courses and programs I have taken and written in the past, switching from a parent to child variable was straightforward but this is quite the opposite !
Any help is appreciated, thank you in advance ! :D
There is no assertion in line 588 of the source file in your link. That github upload dates back to 2014. Why not search the winctrl3.cpp source file in your own Visual Studio installation instead? In my own installation, it is in function PreSubclassWindow() and there is indeed an assertion there:
// CCheckListBoxes must be owner drawn
ASSERT(GetStyle() & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE));
That is the CCheckListBox must be owner-drawn. Find the CCheckListBox constructor code above, you will notice that it calls the CListBox (parent-class) constructor, applying either of the two owner-drawn styles. Instead, the CListBox constructor calls CWnd::Create() with the "LISTBOX" Windows Class-Name as a parameter. That is, it seems to be a MFC-implemented control, overriding the CListBox class, with an owner-drawn style. There is no mention of a native "Check-ListBox" class or style in the Win32 documentation either. Also the CCheckListBox documentation (in the link you posted) clearly states: CCheckListBox is only for owner-drawn controls because the list contains more than text strings.
Therefore:
If you are creating the control using a resource script, add an owner-drawn style (eg LBS_OWNERDRAWFIXED) to the control (or set the Owner-Drawn property in the property editor).
If you are creating the control programmatically make sure you are calling the CCheckListBox constructor, not the CListBox one.
Not sure what you mean about the scroll-bar (and why you mention it), doesn't the list-box display a scroll-bar automatically (WS_VSCROLL style - or property), do you have to do something on your own?
EDIT:
Forgot to mention, if you are creating the control using a resource script use the Class Wizard to add a member variable (of "Control" type, not "Value") to the dialog class. The new variable must be of type CCheckListBox (MFC class). This will subclass the control. If the old project already had a CListBox member variable change it to CCheckListBox.
Related
I just started the GUI development, i had started on C++Builder but i switched to Visual Studio for differents reasons. But in Visual Studio, i've got a big problem :
In the GUI development interface (rc file) i can create buttons and place it, but i can't change there names. The name for all of MFC components i placed is initialize to a default name which i can't call and i can't change the property by the properties interface, i can change the Text, for change the Label of the Button, but not the name...
It's very incomfortable because by that i can't call my buttons for do anything, i have the same problem for Listboxs, so i can't modify my list because i can't call there
I just want to modify access my component by my c++ code for modifying this component
enter image description here
Thank for your help !
The MFC way of doing event handling is a bit more elaborate.
After the control is created on the form in the designer, an ID is generated ("IDC_BUTTON1" in the attached screenshot).
This is the ID that will be used for accessing this UI control from the code.
All this can be done via the designer also as shown in this article.
Basically, in the background this generated ID is put in a 'message map'
(more about message maps here).
In short 'message map' is used to specify what action needs to be performed when a certain type of action is done on the UI control by the user.
For, example if the button click is to be handled then in code:
the message map would look like:
BEGIN_MESSAGE_MAP(CSurface3DView, CView)
ON_BN_CLICKED(IDC_BUTTON1, CallMyFunction)
END_MESSAGE_MAP()
'ON_BN_CLICKED' is a predefined event macro.
The 'CallMyFunction()' function has to be declared with 'afx_msg' in the class. Besides please, have a look at data exchange mechanism as well. This know-how about data exchange will come in handy going forward.
I searched on the forum and I don't find a solution for my issue. So I hope you can help me :)
I work on a personal project for SFC designing (Sequential functional chart) and I'm working with visual studio in SDI(I'm using MFC library). If you see the "design" of an SFC you can see the different elements needed to compose this. So you can find Step, Transition, and more. If I take a step for explaining my issue, after double click on the step a popup dialog is opened with the elements to define this step (actions on this step, and more). The issue is here, I can't see two or more step elements at the same time. I want to reuse the existing concept on other software, see this.
Step close
Step open
Dialog to add
My question is, how I can implement a dialog with my graphic element in mainframe (In this case, a step)? I don't know how I can insert a dialog with my element, I think I need to use CFormView, but I don't know.
This dialog needs to be resizable and reduce directly by the step graphic.
any idea?
Thank you in advance! Sorry for my English ..
Sorry, I think my request is not clear .. (Thank you for your answer)
The context, it's an SDI application with the Document/View architecture. Actually the view is derived from CScrollView.
So, in the document class, you have the different lists of components for make SFC (Steps, transitions and symbols ..). I'm working today on Step element.
The user inserts a new step, the step is draw on the view like this :
enter image description here
And now the user want change the events on this Step, for this after double click on the step the events editor is opened at right of step draw, like this :
enter image description here
For this, I've created a new dialog resource and create the class by wizard in CForwView derived class. In step attribute, you can find one instance of this derived class (The derived class of dialog).
But this doesn't work correctly, I think my method is bad. At the first try, I have sent the pointer of the current document to the "CFormView::Create" function for having the "Save" button active with the focus on the FormView. But after destroying the step, the instance of FormView is destroyed and the document with the instance of formview ...
No problem, you can use "Create" within CCreateContext a null pointer. But with the document or without I have a lot of problems (graphic design not correct in FormView, regularly (not systematic I have assert fail on Proc exchange (for differents reason)). But the "concept" is good, the editor follows the draw if I scroll, I can open or close the editor at any time and on any elements.
For the old capture, it's my SFC designer "model". My application is a complement to this application, so I want a similar design. I don't know how work my model application ..
On my application all is draw by MFC GDI, I don't use ActiveX or other tools.
So what is the correct way to implement one instance of editor by instance of step ?
For the implementation on this FormView I have :
- Make new dialog in ressource
- Create a derived class of CFormView with the created dialog
- Add one instance in attributes of Step element
- "OnDbClickOnStep" -> Call "Create" with the good position / size, pointer of mainview (in my case the CSrollView derived class)
- Done, FormView inserted in a mainview, I can edit my step events.
? Not done, I lost save button and other function linked to the document with the focus on a control in FormView. The app want a document with this view, how to override this ?
? Error in Proc exchange, for different reason...
You have an idea ?
You normally don't draw anything in the "main frame" (or the "MDI clild frames", in the case of a MDI application), this is done by the library, and imo sufficiently so. You display your data in a CView-derived class.
CView is the base class of all other MFC view classes. It's a simple graphical class - you need to paint it yourself in the OnDraw() member.
CScrollView is a descendant of CView, adding scrolling functionality (scroll-bars are automatically displayed if the scrollable area is bigger than the visible window area).
CFormView is a descendant of CScrollView, displaying a dialog resource-script, containing "controls" (edit-boxes, check-boxes, images, ActiveX etc).
As in your case the "controls" won't be initially known (except maybe for some few special cases) and rather programatically created, the resource script will most likely be empty, so using either CFormView or CScrollView will basically be the same. I would suggest starting with CFormView, and "downgrade" it to CScrollView if CFormView is not necessary or causes you troubles.
What are those "Step" items shown in the pics? ActiveX controls, child dialogs maybe? These work best as child controls on a dialog window. Are they already implemented, or they are just pics of some other software? Btw ActiveX is a way to define controls that can be used in other projects too, without having to include them in the project source.
I understand there are functions that can easily write windows registry, however I found out that in new MFC project created with wizard, some information (like split bar position, visibility of controls) gets stored automatically (or at least I found no CWinApp::Write* calls in the project). Since I have also older projects that don't have this behaviour I need to figure out how to make this without help of project wizard. Would anyone please know how does this work?
The MFC control state saving magic happens in the 'New' MFC Feature Pack, specifically in the SaveState methods, for example CMFCToolBar::SaveState.
To take advantage of this you'll therefore need to upgrade your Toolbars and Menus to use the newer controls and upgrade your application to inherit from CWinAppEx. I recommend that you use a New MFC Wizard based app as a guide on how to upgrade your old MFC app.
Most of the information is saved in CPane::SaveState(), thus if you want state of some component saved, you need to use classes derived from CPane. (for more info here is the class hierarchy).
The process of saving window states is initiated through CFrameImpl::OnClosingMainFrame(). This function in turn calls CWinAppEx::SaveState() which saves some application settings and then ALL instances of CMFCToolBar (they add themselves to global list of CMFCToolBars in call to OnCreate). In a similar way all dockable panes are saved but the list belongs to your main frame. Then positioin and size of your main frame is saved.
CViews and CFrameWnds are somewhat less favored, for what I found and tried out, the only information saved was visibility.
I used that loooong time ago. If I correctly reminds it, you should save the informations you want in a overridden CWinApp::ExitInstance() before calling base class method, and you load them in CWinApp::InitInstance. Be sure to allow for default values, because at first run, there will be nothing to load, and do not forget to call (or copy) base class.
I'm turning mad with a little problem with Visual Studio 2008 and MFC. I'm working on a project actually and I'm trying to create an SDI Application. Right, now I want to add a dockable DialogBar. Well, the first time I added it with the resource view, I could create the bar without problems.
But... I want to add some controls like a couple of ListBox, buttons and so on. The program doesn't allows me to create member variables for these controls. The option appears in grey.
Searching a little, I found that it's mandatory to create a new class derived from CDialogBar and "enhance" it with the Message handler and so on. I've been reading some tutorials and it didn't work for me.
Can you please help me? I'm starting to get nervous, the use of dialogbars is mandatory in my design and I've never implemented them before.
Thank you very much, and sorry for my poor english.
You can add a control member variable by hand instead of using the wizard. All it takes is a call to DDX_Control in the dialog bar's DoDataExchange function.
But CDialogBar-derived classes do not handle control clicks. The CDialogBar class forwards all of those messages to the dialog bar's parent window. So be prepared to add the message handlers to the parent (usually CMainFrame).
For learning purposes you might try creating your dialog bar as a CDialog first, to see the proper code lines and message map entries supplied by the wizard. Then you can copy/move these details as appropriate into your actual code project.
I'm trying to call the OpenThemeData (see msdn OpenThemeData) function but I couldn't determine what are the acceptable Class names to be passed in by the pszClassList parameter.
HTHEME OpenThemeData(
HWND hwnd,
LPCWSTR pszClassList
);
Could anybody tell me what are the acceptable class names that I can pass into that parameter?
Thanks!
The article Parts and States on MSDN contains a table which shows the control classes, parts, and states. The values in the table are defined in Vsstyle.h and Vssym32.h.
Here is a quick reference:
BUTTON, CLOCK, COMBOBOX, COMMUNICATIONS, CONTROLPANEL, DATEPICKER, DRAGDROP,
EDIT, EXPLORERBAR, FLYOUT, GLOBALS, HEADER, LISTBOX, LISTVIEW, MENU, MENUBAND,
NAVIGATION, PAGE, PROGRESS, REBAR, SCROLLBAR, SEARCHEDITBOX, SPIN, STARTPANEL,
STATUS, TAB, TASKBAND, TASKBAR, TASKDIALOG, TEXTSTYLE, TOOLBAR, TOOLTIP,
TRACKBAR, TRAYNOTIFY, TREEVIEW, WINDOW
The answer to the question Windows Visual Themes: Gallery of Parts and States? provides a "Parts and States Explorer" application where you can browse and test most of the styles.
I know this is an old question, but I want to give an updated answer (2018) for those who come here from Google.
The accepted answer of DavidK says to look into the file "AeroStyle.xml" where the themes are defined. This file was part of the Windows 7 SDK, but has been removed from the Windows 10 SDK, so the accepted answer is not useful anymore.
The answer of splash links to the MSDN where the list of theme names, parts and states is highly incompetlete and not updated.
The themes are drawn by UxTheme.dll which reads the images and colors, etc. from the file aero.msstyles in the folder C:\Windows\Resources\Themes\Aero on Windows 10.
To see the classes inside the XYZ.msstyles file use msstyles.Editor:
https://github.com/nptr/msstyleEditor
Several themes can only be obtained if you pass the correct window handle. There seems to be an automatic mechanism which detects the type of control from a window handle. If you pass the handle of the wrong window you may get another theme handle than expected or even NULL.
Microsoft internally has changed all their code to use OpenThemeDataForDpi() instead of OpenThemeData() because each monitor on Windows 10 may have a different resolution.
The problem that we have here is a severe lack of documentation in the MSDN and a lack of an API function to enumerate all availabe themes. Shame on Microsoft (once more).
You can look in "AeroStyle.xml" as a previous poster noted, which gives an exact list for Vista/Aero. However, if you want to play safe (and you probably do) the class names should, in general, be Windows class names of Windows common controls. For example, push buttons and check boxes use the class name "Button", the edit control "Edit", etc. I generally pick the class name of the control that's closest to whatever custom element I'm working on is, and use the theme data for that. That way you'll get code that works with XP, Vista and (hopefully) Windows 7, regardless of what the user's selected theme actually is.
However, unless you use raw Win32 a lot, you probably don't do much control creation directly using the class name. The class names are rather liberally sprinkled throughout MSDN. A good place to start is usually the "CommCtrl.h" file from the Platform SDK, which has a lot of them, and they're always described in the MSDN help on the individual common controls. You can also often learn them by looking at how dialogs are defined in .rc files by opening them in a text editor: these contain the class name for the controls.
Class names depend on the theme. For example, as the documentation for OpenThemeData states:
Class names for the Aero theme are
defined in AeroStyle.xml, which is
found in the Include folder of the
Microsoft Windows Software Development
Kit (SDK).
It has nothing to do with Aero, which even doesn't exits on XP !
See the source code of OpenThemeData()..