I am embedding Excel in winform using DSOFramer control.
In case of Excel 2010 the context menu on right mouse button click will not open.
It looks as if the control loses focus on right click.
I edited the DsoFramer source code before so I am comfortable with it. Anybody know of any possible hack in order to make this work?
This is what I did:
STDMETHODIMP_(void) CDsoFramerControl::OnCtrlFocusChange(BOOL fCtlGotFocus, HWND hFocusWnd)
{
//TRACE2("CDsoFramerControl::OnCtrlFocusChange(fCtlGotFocus=%d, hwndCurFocus=%x)\n", fCtlGotFocus, hFocusWnd);
// if (!(m_fInFocusChange) && ((fCtlGotFocus) || !IsWindowChild(m_hwnd, hFocusWnd)))
// {
// OnUIFocusChange(fCtlGotFocus);
// }
}
Related
I'm creating my first C++ wxWidgets application. I'm trying to create some kind of split button where the options are displayed in a grid. I have a custom button class which, when right-clicked on, opens a custom wxPopupTransientWindow that contains other buttons.
When I click on the buttons in the popup, I want to simulate a left click on the main button. I'm trying to achieve this through events, but I'm kinda confused.
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetGrandParent();
mBtn->SetLabel(this->GetLabel());
mBtn->Refresh();
wxCommandEvent event(wxEVT_BUTTON);
event.SetId(GetId());
event.SetEventObject(mBtn);
mBtn-> //make it process the event somehow?
wxPopupTransientWindow* popup = wxDynamicCast(this->GetParent(), wxPopupTransientWindow);
popup->Dismiss();
}
}
What is the best way to do this?
You should do mBtn->ProcessWindowEvent() which is a shorter synonym for mBtn->GetEventHandler()->ProcessEvent() already mentioned in the comments.
Note that, generally speaking, you're not supposed to create wxEVT_BUTTON events from your own code. In this particular case and with current (and all past) version(s) of wxWidgets it will work, but a cleaner, and guaranteed to also work with the future versions, solution would be define your own custom event and generate it instead.
I'm not sure why am I getting this visual artifact?
Here's how to repro:
I'm using Visual Studio 2017 Community. Create a new C++ -> MFC project:
Then specify "dialog based":
Then build as "Debug" x86 app and run it.
So I'm running it on Windows 10.
When this dialog-based process has focus, it looks as I would expect it:
but if I switch keyboard focus to some other app (by clicking on it), this dialog-based process still retains its title bar color:
I'm not sure if it's just a matter of a visual glitch or if there's a deeper mess-up with the window message handling. How do I correct it? (This wasn't an issue with older MFC projects.)
I managed to replicate your problem and found a quick fix for it.
You need to add the WM_ACTIVATE message handler to your main dialog, comment out the base class OnActivate and modify it like this:
void CMFCApplication1Dlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
//CDialogEx::OnActivate(nState, pWndOther, bMinimized);
// TODO: Add your message handler code here
this->Default();
}
CWnd::Default call is needed to keep the active/inactive visualization of the default button.
OK, as much as I appreciate #VuVirt's solution, it doesn't completely remove all the bugs that are shipped in the default Dialog-based solution in VS2017. It solves the title bar focus issue, but while continuing to develop my project I encountered another bug. So I'm copy-and-pasting it from my comment to his answer:
There's still some kinda screw-up there. I'm not sure if it's related to this fix or not. Ex: If you create a button and then in its handler try to do: CFileDialog d(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_EXPLORER, NULL, this); d.DoModal(); to open a file picker dialog. When file picker opens up, close it and see if the title bar of the parent MFC dialog window goes back to being active. In my case it remains inactive until I click onto the Windows taskbar and then back onto that MFC app.
After banging my head against the wall trying to see what is going on there, I decided to try an earlier solution proposed by #zett42 in the comments to my original question (i.e. to replace CDialogEx with CDialog) and it worked! All the bugs are gone!
So here's my verdict: CDialogEx is buggy af.
The resolution is quite simple: When you create a new dialog-based project use project-wide find-and-replace (in the Edit menu) and replace all occurrences of CDialogEx with CDialog. And that is it. (I tried to use VS2017's refactoring tool for that but it messed it up and didn't replace it all. So simple search-and-replace does the job.)
And if you think that you'll be missing some functionality without CDialogEx, then you won't. All it does (besides introducing bugs) is that it adds background images and colors to the dialog.
So until MS fixes those glaring bugs in their templates I'm sticking with this approach.
This seems to be a bug in CDialogImpl::OnActivate and CDialogImpl::OnNcActivate:
void CDialogImpl::OnNcActivate(BOOL& bActive)
{
if (m_Dlg.m_nFlags & WF_STAYACTIVE)
bActive = TRUE;
if (!m_Dlg.IsWindowEnabled())
bActive = FALSE;
}
void CDialogImpl::OnActivate(UINT nState, CWnd* pWndOther)
{
m_Dlg.m_nFlags &= ~WF_STAYACTIVE;
CWnd* pWndActive = (nState == WA_INACTIVE) ? pWndOther : &m_Dlg;
if (pWndActive != NULL)
{
BOOL bStayActive = (pWndActive->GetSafeHwnd() == m_Dlg.GetSafeHwnd()
|| pWndActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE));
if (bStayActive)
m_Dlg.m_nFlags |= WF_STAYACTIVE;
}
else
{
m_Dlg.SendMessage(WM_NCPAINT, 1);
}
}
This is meant to give CDialogEx the ability to stay active, for example, when CMFCPopupMenu is shown.
But m_Dlg.SendMessage(WM_NCPAINT, 1) is a suspicious call. The usage doesn't match the documentation for WM_NCPAINT:
Parameters
wParam
A handle to the update region of the window. The update region is clipped to the window frame.
lParam
This parameter is not used.
Additionally, OnNcActivate has an override based on IsWindowEnabled(). This seems to be a patch to fix the earlier problem in OnActivate. But it causes problems elsewhere, for example when using CFileDialog in CDialogEx
Suggested solution:
Modify CDialogEx::OnActivate so that it runs the default procedure. Or, change it such that it will force repaint.
BOOL CDialogEx::OnNcActivate(BOOL active)
{
if(m_nFlags & WF_STAYACTIVE)
active = TRUE;
return(BOOL)DefWindowProc(WM_NCACTIVATE, active, 0L);
}
void CDialogEx::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
Default();
}
or
void CDialogEx::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
Default();
//save the previous flag
UINT previous_flag = m_nFlags;
m_nFlags &= ~WF_STAYACTIVE;
// Determine if this window should be active or not:
CWnd* pWndActive = (nState == WA_INACTIVE) ? pWndOther : this;
if(pWndActive != NULL)
{
BOOL bStayActive = pWndActive->GetSafeHwnd() == GetSafeHwnd() ||
pWndActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE);
if(bStayActive)
m_nFlags |= WF_STAYACTIVE;
}
if(previous_flag != m_nFlags && previous_flag & WF_STAYACTIVE)
{
//if the flag is changed,
//and if WF_STAYACTIVE was previously set,
//then OnNcActivate had handled it wrongly, do it again
SendMessage(WM_NCACTIVATE, FALSE); //<- less wrong!
}
}
This should work with CMFCPopupMenu for example. The MFC menu will open without deactivating the dialog.
I am not sure what SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE) is for, I haven't been able to test it... If it's necessary, it seems the code could be added on OnNcActivate, and then OnActivate is left alone.
I've got an CMFCRibbonButton that displays a text and an icon. When I compact the ribbon, in the end only the small icon is shown.
Is there a way to tell the button not to get compacted into small icon state, but always show the text as well?
I tried pButton->SetCompactMode(FALSE); without success.
To be sure, CMFCRibbonButton::SetAlwaysLargeImage() is not what you are looking for? I ask, because when only an icon without text is displayed, it is usually the panel the button sits in that has collapsed. See CMFCRibbonPanel::IsCollapsed(). If you want to modify the behavior of the panel so that it won't collape, you could try to subclass CMFCRibbonPanel and play with overrides. The MFC Ribbon is not completely documented but my best bet is CMFCRibbonPanel::IsFixedSize():
class CMyPanel : public CMFCRibbonPanel
{
...
BOOL IsFixedSize() const { return TRUE; }
...
}
If this doesn't work you have to see yourself what happens in NotifyControlCommand or OnUpdateCmdUI when the panel collapses and modify the behavior as needed.
I am a new comer in MFC programming. I have already wrote a program, and I want to display the program in a graphical interface. So I use MFC dialog to realize it, but it does not work when runs.
Once the OK button is clicked :
void CTest1Dlg::OnBnClickedOk()
{
UpdateData();
FILE *stream;
freopen_s( &stream, "out_file.ps", "w", stdout ); // reopen stream as .ps
if (mode == 1) //main() in my code
{
ActiveAuthoring();
}
else if (mode == 0)
{
XYAuthoring();
}
else
{
ActiveAuthoring();
}
cout<<"showpage"<<endl;
UpdateData(FALSE);
OnOK();
}
My code is in converter.cpp, so first I change converter.cpp to converter.h and include it in Test1Dlg.cpp. And then when the OK button click run the main() in my code.
However, I discover that it seems the parameter does not transfer from the graphical interface to my code, although I relevant the edit control box to every parameter. So the dialog does not work. Could some one help me?
EDIT
The eight edit control boxes are the parameters I used in my coverter.cpp.
My code is aim to use eight parameters to generate some strings, these strings are saved in a file named as out_file which format is .ps.
There are two basic ways you get data from dialog controls to "your code"... if you're using the Visual Studio dialog editor and adding the controls there, it will generate code inside of virtual void DoDataExchange(CDataExchange* pDX) for you to move data to and from your controls when the dialog gets initialized and terminates. You'll have a line like DDX_Text(pDX, IDC_DIGITS, m_Digits); that the IDE adds that does the exchange. You can also just set and get the data directly if you wanted, e.g. GetDlgItem( IDC_DIGITS )->GetWindowText( m_Digits );
I'm building a UI using wxWidgets in windows platform with C++. I have a toggle button in the ribbon. I initialize the button as follows:
m_cell_bar->AddToggleButton(RIBBON_CELLSELECTMODE, wxT("Cell Select"), wxBitmap(selectcell_xpm), wxEmptyString);
To fulfill the purpose of using a toggle button, I need to assign different events from unchecked->checked and checked->unchecked events. If it was a normal toggle button I would use:
buttonid->GetValue()
But it's not.. So how can I reach the state?
Thanks...
It doesn't look like they provide a method for getting the checked state of a button (I'm working with 2.9.2). However it looks like you can get it using code like this (I've not tried this, just looked through the wx code):
wxRibbonButtonBarButtonBase* button = m_cell_bar->AddToggleButton(RIBBON_CELLSELECTMODE, wxT("Cell Select"), wxBitmap(selectcell_xpm), wxEmptyString);
// Store the "button" pointer for use later
// ...
// Sometime later
if((button->state & wxRIBBON_BUTTONBAR_BUTTON_TOGGLED) == 0)
{
// Not checked
}
else
{
// Checked
}