How to right button drag with Win32 API? - c++

I implemented the IDropTarget interface and the drag & drop (file from explorer) works well.
When I drag & drop a file with right mouse button, the context menu does not popup.
So I think it's my responsibility to show the context menu,
But in IDropTarget::Drop method, (grfKeyState & MK_RBUTTON) is always 0.
How can I know if the drag mouse button was right?
And is there a special method to show menu and receive the selection after the drop?
(I prefer the Win32 API way, I don't use MFC.)

I guess (grfKeyState & MK_RBUTTON) is always 0 because when the Drop() method is called, the mouse button is already released (you've just made the drop) - so naturally the keyboard/mouse state flags would indicate that it is indeed released.
What you can (and should, according to the documentation) do, is to decide ahead the course of action you take on Drop() when you're handling DropEnter(). I haven't tried it myself, but I'm quite sure that the MK_RBUTTON flag should be set there. You can check that flag when your drop target's DropEnter() method is being called, save it and then open the context menu yourself when Drop() is called. This is not the cleanest solution, but I don't know if there's a way to make Windows show a context menu for you.

Related

Drag and drop in MFC Dialog

I'm trying to add drag and drop functionality to a control on a property page which is programmatically "wrapped" inside an MFC dialog at runtime. This "wrapping" involves instantiating the property page as a member of the dialog, and then resizing it and positioning it to the dimensions of a picture control which is on the dialog in the .rc file. I'm not sure why things were done this way, other than to maybe standardise the appearance of property pages in the app, but in any case I end up with this complicated hierarchy of windows, a control inside a property page inside a picture control inside a dialog.
The control which I want to accept dragged files has DragAcceptFiles invoked on it, but I think the WM_DROPFILES message for the control is being discarded before it reaches the control, because one of the parent windows doesn't accept dragged files. I considered calling DragAcceptFiles on all the parents, and passing WM_DROPFILES down the chain of windows, but I don't want to do that because they won't have handlers to accept the files, and will show the icon indicating files can be dropped on them regardless.
Any help on figuring out how to get the WM_DROPFILES message to my control would be much appreciated.
At the parent level, implement an override for virtual CDialog::PreTranslateMessage(MSG* pMsg)
This gives you a chance to see the WM_DROPFILES message and redirect them to a handler in the property page.
I figured this out in the end by calling CWnd::BringWindowToTop() on both the control I wanted to drag files onto, and also the dialog that the control was on.

CListCtrl (MFC) selection click passes through to control UNDERNEATH the list

My CListCtrl (Report View, single column) ignores item selection when there's another control behind the CListCtrl. It's as if the click passes through to the control BEHIND the CListCtrl.
Selection is fine if the list item isn't on top of another dialog-box item.
It's baffling because the CListCtrl's z order is ABOVE these other controls. Can anyone suggest something I could try to make the CListCtrl accept a click even when there's another overlapped control? Thanks!
User Spy++ to check the message flow. And to check if another control is above your control! Maybe there is something wrong with you´r z-order even if you think that the control is above. Also check if you overwrote WM_NCHITTEST

Two-state button that mimics a checkbox in MFC

I want to make a button on an MFC tool bar that can be pressed and retain it's state until pressed again (like a check box) but I don't want a tick box. I'd ideally like a button that changes between two icons and uses DDV to change the value of a boolean on being pressed. How would I go about this.
As a side question I could really do with a good book on MFC. I've got Programming Windows with MFC 2nd edition, but was wondering if there was anything that went into a bit more detail?
Use ON_UPDATE_COMMAND_UI to set the state of the button. e.g. a typical handler will look like this:
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_UPDATE_COMMAND_UI(ID_MY_BUTTON, OnUpdateMyButton)
END_MESSAGE_MAP()
...
void CMyView::OnUpdateMyButton(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetCheck( isButtonPressed() );
}
With regard to good MFC documentation I recommend Professional MFC (Mike Blaszczak) - it's a little old but very good.
From the documentation of the CToolBar Class:
To create a check-box button, assign it the style TBBS_CHECKBOX or use a CCmdUI object's SetCheck member function in an ON_UPDATE_COMMAND_UI handler.
Draw a Radio Button on Dialog box.
Select Radio button & go to button Properties page.
Set Push Like property & set as "True"
Add event handler for the same control & take Boolean variable.
Use API -> "CheckDlgButton(IDC_RADIO1, 1);" for set status as per Boolean variable value.
for more details. visit below link.
https://www.codeproject.com/Articles/530/A-Better-Bitmap-Button-Class

Is it possible to change the location of the main top-level menu in an MFC MDI app?

I have an app with a customized frame (i.e., caption/titlebar, borders). I customized the frame by removing the WS_CAPTION style, and overriding OnNcCalcSize to reserve a custom-sized area for the caption, which the app paints in OnNcPaint.
A side effect is that the menu bar no longer displays, which is OK because I want to customize the appearance & location of the main menu. Unfortunately, I don't know how to do that. I would like the "File" menu to be further from the left edge than it is with the standard menu bar.
An acceptable alternative would be to remove the menu entirely, and use OnNcHitTest, OnNcPaint and OnNcMouseMove to manage a hand-coded replacement for the top-level menu.
I've never seen a way to modify the looks of the standard menu. You can remove it (remove the creation code from your InitInstance) and then code a replacement. I wouldn't do that in OnNcXXX though, rather make a new custom control that you position at the top. Or you could have a look at the MFC Next themed menus and write a custom UI renderer. It may be enough to override a few functions left and ride to set the alignment of the menu.
It's an MFC MDI app -- InitInstance is not where the menu is being created. I have tried to get rid of the menu (and succeeded, temporarily) but the MFC framework seems to be "putting it back" -- I think the MDI model has the child windows modify the menu, but the code that does that seems to be buried in the framework somewhere (or else I just haven't been able to find exactly where it happens in the application's code, but I suspect it's happening inside the MFC framework code). If I knew where, I might be able to override the methods(s) and take control... I think.
What would be the reason to write a custom control vs. handling OnNcMouseMove & OnNcLeftButtonDown, e.g.? I don't expect to need the functionality in any other app (a new app would be coded in C#, probably), so I'm looking for ease of implementation, not code reuse.

"Sticky" MFC popup menu

I currently have some toolbar buttons with a small arrow on the side (TBSTYLE_EX_DRAWDDARROWS) that, when clicked, result in a popup context menu being displayed under the button. This is done by constructing a custom popup menu and calling TrackPopupMenu.
The client now wants to be able to select multiple options from the menu before it closes, so that multiple options can be be modified without the need to re-open the menu and wait for an intermediate redraw between each change.
For example:
User clicks dropdown button
Dropdown menu appears (modal, waits indefinitely for user action)
User clicks some item (e.g., toggle a checkmark)
Timer (e.g., 500ms) starts
If timer expires, the menu is closed and all selected actions are executed.
User clicks another item before the timer expires, go back to 4.
The best I can come up with is to redisplay the menu by calling TrackPopupMenu multiple times. This makes the menu "flicker" when you select an item, and will probably require me to start a thread in order to do the timeouts, which I would rather avoid.
Rather than a menu, put up a dialog box with the options on it. A dialog can easily do all that is required.
A menu that doesn't close when you click it will just seem wrong. A dialog that closes by itself will seem wrong too, but it's probably the least of two evils.
Edit: If there's anything I've learned with Microsoft, it's don't try to fight the default behavior. You're asking for trouble if you do.
If you're building your menu dynamically I can see how automatic sizing can be handy, but it's not hard to do in a dialog either - make the dialog really big and before it becomes visible, enumerate the children and take a union of all their rectangles, then resize to that. Checking the boundaries to make sure they're on-screen is just a few if statements with OffsetRect. Checkboxes are trivial; icons less so, but still not bad.
One additional enhancement that would be easy to add is to dismiss the dialog immediately on a double-click.
Following #Mark Ransom's answer, you should put up a dialog box. But you can make the dialog modeless and make it close itself when you click outside of it (i.e., the dialog loses focus). That way it could behave more like a menu.
Notice that normal menus never go away by themselves, you always have to click somewhere outside the menu (or one of its options) to make it disappear.