What's the right way to connect a slider to a member variable in MFC? What I've done so far:
Dragged a slider in to my dialog in the resource view and given it an ID
Right clicked on the slider and chosen Add Variable
Set the variable to Control variable and the Category to Value and also set the Min value and Max value to desired values.
This creates a member variable of type int in my dialog class and also adds some stuff to the DoDataExchange method.
However, the DoDataExchange method is only called once when my dialog is created, what do I have to do to make my member variable update when I drag the slider? Should I have set the Category to Ctrl instead and manually managed the range, and intercepted the WM_HSCROLL messages?
(This is a non modal dialog by the way)
Call UpdateData to do the DataExchange passing TRUE to save and validate the data to your variable and FALSE to set the control value based on your variable, ie. passing data into the control. More information about UpdateData:
http://msdn.microsoft.com/en-us/library/t9fb9hww(v=vs.80).aspx
and for general data exchange mechanism:
http://msdn.microsoft.com/en-us/library/xwz5tb1x(v=vs.80).aspx
Yes, you call UpdateData() from within the handler for the control's WM_HSCROLL (or WM_VSCROLL) if it's a vertical slider). See http://msdn.microsoft.com/en-us/library/ekx9yz55%28v=vs.80%29.aspx .
Related
My application supports the IE (InternetExplorer) browser. When the back/forward buttons are clicked and there is nothing to go back or forward to, Webbrowser.GoBack() and Webbrowser.GoForward() are causing a crash.
Is there any way to know if I can go back before I actually call GoBack()? I took a look at the CWebBrowser2 class functions, but I couldn't find anything as such.
Is there any API to help on this, or any alternative approach to handle this?
Is there any way to know if I can go back before I actually call GoBack()?
Per the IWebBrowser2::GoBack() documentation:
Use the DWebBrowserEvents2::CommandStateChange event to check the enabled state of backward navigation. If the event's CSC_NAVIGATEBACK command is disabled, the beginning of the history list has been reached, and the IWebBrowser2::GoBack method should not be used.
And likewise in the IWebBrowser2::GoForward documentation:
Use the DWebBrowserEvents2::CommandStateChange event to check the enabled state of forward navigation. If the event's CSC_NAVIGATEFORWARD command is disabled, the end of the history list has been reached, and the IWebBrowser2::GoForward method should not be used.
And per this discussion thread:
Create a couple of BOOL member variables in the class that processes the
ON_UPDATE_COMMAND_UI notifications for the 'back' and 'forward' toolbar
buttons -- one for each button state. Initialize them both to FALSE in
the ctor. Handle the OnCommandStateChange event, and watch for the
CSC_NAVIGATEBACK and CSC_NAVIGATEFORWARD values in the 'nCommand'
parameter. When you get the CSC_NAVIGATEBACK value store the 'Enable'
parameter value into your BOOL member variable for the 'back' button
state. Do the same thing for the 'forward' button state variable when
you get CSC_NAVIGATEFORWARD value. In your OnUpdateButtonForward and
OnUpdateButtonBack handlers, call pCmdUI->Enable using the corresponding
button state member variable.
So, use the browser's CSC_NAVIGATE... state changes to know when it is safe to call GoBack()/GoForward()`. These are the same events that IE uses to enable/disable its own Back/Forward UI toolbar buttons.
I've added a combo box to my MFC dialog box. And I've added both a control variable (m_wndImportMode) and a value variable (m_nImportMode).
I'm able to use both variables just fine. And I can use the control variable to populate the control just fine. My problem is where is the correct location to populate my control?
If I populate the combo box before DoDataExchange() then my control variable has not yet been initialized. If I populate the combo box after DoDataExchange(), then it populates fine but the value does not get set.
BOOL COptionsDlg::OnInitDialog()
{
// If I populate my combo box here,
// my control variable is not yet available
// This will ultimately call DoDataExchange()
CDialog::OnInitDialog();
// If I populate my combo box here,
// DoDataExchange() has already been called and
// so it will not have selected the correct item
// before there were any items
return TRUE; // return TRUE unless you set the focus to a control
}
Playing with this a little more, I can see I can populate the control before calling CDialog::OnInitDialog() if I use GetDlgItem() instead of my control variable (which has not yet been initialized), and then the default item will correctly be set as I want. But doesn't the MFC framework provide for populating list controls in a dialog box and still using DoDataExchange()?
I resolved this by using GetDlgItem() to retrieve the combo box, and then populating it before CDialog::OnInitDialog() is called. This works as intended.
I'm not sure what I might be doing differently if this is not an issue for anyone else.
I have a PropertySheet containing 6 PropertyPages. During OnInitDialog of each page, a setting structure assigns initial values to the dialog controls.
However at some point, I want to change my setting structure and each dialog must show newly assigned values for each control it has. Like resseting every dialog.
To achive this, I tried removing and adding all 6 pages but it didn't work. How can I reset every dialog control without manually setting new values to controls.
If I can call OnInitDialog function it would work. However I cannot call OnInitDialog twice.
I'm trying to add a progress control in my dialogs, that will step upon every iteration of a loop until completion. I've never played around with progress controls before, so I'm totally clueless as to where I should start. I've added a progress control resource view into my dialog, but it just shows up as an empty progress control. I'd like to have the progress control dynamically appear/update when after pressing a button an image from somewhere stars being loaded.
I am trying to add a progress control on a dialog box in Visual c++ environment.
After adding this tool the following code added to main.cpp :
void CPanoramicsampleDlg::OnNMCustomdrawProgress1(NMHDR *pNMHDR, LRESULT *pResult){
}
I can show procedure of loading in a Text control as follow:
sprintf_s(pack1,"Data%d%%",Event);
::SetWindowText(GetDlgItem(IDC_Static)->m_hWnd,pack1);
so in this way I can see loading process as %d in a text window but I don't know how to show loading procedure by progress control and how and where to define range or even progress bar handle for this progress control so on.
finally I would like to know is there any function for progress control for example:
::EnableWindow(GetDlgItem(IDC_Progress1)->m_hWnd);
You should first add a variable for the control, by right-clicking on the progress bar in the dialog editor, and choosing Add Variable... Your dialog class will then have an instance of a CProgressCtrl class on which you can then call the members that IInspectable has mentioned in his answer. Delete the OnNMCustomdrawProgress1 handler, you don't need it.
e.g.
m_progressCtrl.EnableWindow(TRUE);
m_progressCtrl.SetRange(0, 100);
m_progressCtrl.SetPos(75);
Then whatever that eventParam1 value is that you mention, proportion it between your start and stop value, and call SetPos with it.
Update after comment:
Do the SetRange() in the OnInitDialog() function. If you don't already have an OnInitDialog you need to override it, follow the instructions in the accepted answer of this question to do it.
VS 2008, MFC: add OnInitDialog - how?
As for where you put the SetPos(): You describe that you can already track loading progress in a text control using some or other eventParam1. That sounds like a handler or callback from what ever loading you're doing, and that is where you will instead SetPos() on the progress bar instance.
The CProgressCtrl Class provides the following members that you will have to use:
CProgressCtrl::SetRange: Allows you to set lower and upper bound. These values ideally reflect your starting state and finishing condition.
CProgressCtrl::SetPos: Used to update the current position. You would update the current position where you used to output progress in your edit control.
As an alternative to calling CProgressCtrl::SetPos with an explicit position value, you can set a step increment, calling CProgressCtrl::SetStep, and update the control with a call to CProgressCtrl::StepIt. If you know the step increment ahead of time, this is an easier way to go about updating the current position.
Additional information is available at the MSDN: Using CProgressCtrl.
I have created a simple game using Win32 and gdi. I would like to have a track bar at the bottom that tracks a global variable. I'm just not sure how to add controls. How could I add a trackbar? I can imagine it would get created in the wm_create event.
Do you mean TrackBar or StatusBar?
A StatusBar is normally located at the bottom of a window and displays informational messages about the application status, a TrackBar allows the user to select a value. Do you want to allow the user to select the value of your global variable or do you just want to display the current value of the variable? (I'm not sure if the trackbar will display the current value of the variable without extra work.)
Either way, there are samples for both StatusBar and TrackBar located on MSDN.
The child windows are normally created either in the WM_CREATE of the parent or after the parent window has been created (i.e. when you obtain a valid hWnd for the parent) and after calling InitCommonControls() and/or initializing COM if needed.
To create controls on the fly, in general use the CreateWindow function. With a bit of googling for "TrackBar+CreateWindow" you'll find a number of samples for your question:
i.e.:
http://zetcode.com/gui/winapi/controlsII/
or
http://msdn.microsoft.com/en-us/library/bb760151%28VS.85%29.aspx