I'm developing an application with tab controls. After clicking on an icon in a tab, a popup window opens and the contents of the tab are moved to the popup window.
What I do is simple - change parent of each control within the tab to the popup window (using SetParent()). Everything works great except for listview controls (virtual listview).
After changing the parent, the listview no longer sends WM_NOTIFY notifications.
I've also tested it with non-virtual listview and the same happens.
I've searched all over google and came up with nothing, so any ideas would be appreciated.
UPDATE
After changing the parent, the listview keeps sending WM_NOTIFY notifications to its previous parent. Is this a bug in common controls?
A lot of the common controls cache their parents when they are created. There's nothing you can really do about this except to create them with the right parent in the first place.
One workaround is to register a dummy window class that does nothing more than host the common control in question, and forward messages back and forwards to it. Then you can reparent that window rather than the control itself.
Related
I have some old VB 6.0 code that I need to get running on Windows 10. We are not allowed to use Compatibility mode due to security and client refusal issues.
The only problem I am having is that whenever a button is clicked on the interface the menu items (across the top) become unresponsive. If you mouse over them the shading changes but clicking does not drop down the menu. Additionally, if I generate a message box pop up and click OK the menus come back to life.
I've tried setting focus to the main form in different situations, tried refreshing the parent and child forms. Also added a brand new button with no code behind it - not even an empty click event handler - and that button when clicked causes the same issue.
I should also add that the main form is an MDI form with three child forms. The buttons of course reside on the child forms.
I'm not sure how to proceed with this at this point. I certainly can't have a message box pop up after every button is clicked. Has anyone seen this before or have any ideas as to what causes it?
I have a desktop-like application which has 2 controllers: 'Desktop' which represents desktop icons and 'Taskbar' which represents the taskbar where you find buttons to minimize/restore windows already opened, like MS Windows is working.
The problem I currently have is the approach to "how should I display the window". Infact after doubleclicking the icon, I should create a window, and this could happen both on Desktop controller or on Taskbar controller (or maybe directly on the viewport, because they can be dragged anywhere). However, when I create a window, a new button should be created on the taskbar to minimize/restore it.
Because of this, I thought about handling window in the taskbar controller, however I don't know how to reach the Taskbar controller from the Desktop controller.
I have 3 ideas in my mind at the moment:
The Desktop controller directly adds the button to the TaskbarView, but in this way I'm feeling like violating MVC pattern. Also I need to specify TaskbarView in Desktop views.
The Desktop controller after icon doubleclick fires a custom event on the Taskbar controller. In this case the taskbar opens the windows and adds the button, this approach is quite linear but I don't know how to reference a controller from another controller (in this case, from Desktop to Taskbar)
The Ext.Application register for itemdblclick event on Desktop controller. When this event is fired, it redirects (or call a custom event) on Taskbar controller. After this everything keeps going like point 2. In this way I centralize the Routing functionality (like rails), however could also happen that Application object becomes really big. Also I'm using it as a "gigant controller" to route everything, but this is not really a big problem, thinking about rails it does something similar.
The application should not be split in 2 controllers (so Desktop and Taskbar should be one) and everything will be fine. I don't think this approach is correct.
So, my questions are:
Which approach should I use: 1,2,3,4 (or specify if there is something different)?
What a window should belongs to: Desktop controller, Taskbar controller, something else?
Thanks for any answer
I have a similar setup to you. Personally I would go with choice 2. There is a couple ways to deal with this. One is to have a parent that contains both the Desktop and task bar as its children and it can manage the communication between the two. You can create custom events which the parent listens for and directs them to the correct children.
So for example the parent creates both the task bar and desktop and it listen for icon click events on the desktop. When a click event on the icon occurs the parent receives the events and then internally determines what need to be done. In this case it knows that it needs to call the task bar and create the button for the opened window on it.
You could also look at using a a Mediator design pattern in JavaScript to register senders and listeners. So you could sent it up that the desktop is a sender of icon click events and the task bar is a listener of these events. The click on the icon will send an event to all the listeners of it set in the mediator. This way you don't need a parent to manage it. But personal I like the parent better.
Is there a way to change the position of the popup menu. With top-level windows I can do it by CBTProc Callback Function and MoveWindow. Can I do the same with menus? Needs to be done so that the pop-up menu is located only in the area of its parent window. Something like a light window manager.
Yes, in a WH_CBT hook callback, you'll be notified with an 'nCode' of HCBT_CREATEWND whenever a menu window is created. Test for the class name, standard menu/submenu windows would have a class name of '#32768'. You can then send a MN_GETHMENU message to the window to find out which menu is about to be activated. But as documented, it is too early to move the window when the notification is received, the menu is not even visible yet, so you might need to sub-class the window and process additional messages.
Note that you don't need a hook to be notified when a menu window is shown, you can put a handler for the WM_ENTERIDLE message, test for 'wParam' to see if a menu caused the message, get the menu window from 'lParam' and again send a 'MN_GETHMENU' to find out the specific menu. It is possible to move the window at this point without further message handling. Just be aware that 'WM_ENTERIDLE' will be called multiple times so you need to keep track of you've already moved a particular window or not.
In a Win32 API C++ project, I have a dialog with a tab control (3 tabs) and 3 dialogs that are children of the tab control. I load the main dialog with tab control using DialogBoxParam, and the child dialogs from resources with CreateDialogParam. The main dialog appears with the child dialogs. Clicking the tabs shows/hides the correct child dialog, everything working fine.
After searching around about tab orders I found the WS_EX_CONTROLPARENT style to set on the tab control to get tabbing working into the child dialog windows. This works great, except for one problem: The tab control itself never gets focus, so I can't tab to the tab control to change to a different tab with the keyboard. Keyboard focus goes through the child dialog, to the buttons on the main dialog, then directly back to the child dialog, and never stops on the tab control itself, so I have to click on the tab control to change tabs. It's driving me crazy. Any suggestions?
Update: I managed to work around the problem by forgetting about WS_EX_CONTROLPARENT completely, and making the child dialogs siblings of the tab control. Only side effect seems to be more flashing of controls during a repaint, but would still like an answer, since making the child dialogs children of the tab seems cleaner.
Its not cleaner. The recommended way to create tabbed dialogs is to make the tab pages children of the dialog. The tab control simply controls which of the pages is visible, but is not their parent.
This is especially important when you might try to get XP themeing working on the dialog.
WS_EX_CONTROLPARENT is a style intended to be set on the actual 'tab' dialogs.
I presume you have set WS_TABSTOP on the tab control itself? I imagine that WS_TABSTOP and WS_EX_CONTROLPARENT conflict when simultaneously set as they tell the dialog manager to do two entirely different and conflicting - things when the tab cycle reaches the control.
Lastly, I cannot see any reason at all that flickering should increase because the dialog pages are children of the dialog rather than the tab control.
You can't AFAIK because tabbing cycles through the child controls of a dialog by design. Best you could do is preprocess the tab keydown event and if its after the focus is on the last control in the dialog, focus the tab page and discard the event. Not cleaner than the solution you already have it seems to me.
Even when BorderStyle is set to 0, it is possible to force a window to show up on the taskbar either by turning on the ShowInTaskbar property or by using the windows api directly: SetWindowLong Me.hwnd, GWL_EXSTYLE, GetWindowLong(Me.hwnd, Win.GWL_EXSTYLE) Or Win.WS_EX_APPWINDOW. However, such taskbar entries lack a right-click menu in their taskbar entry. Right-clicking them does nothing instead of bringing up a context menu. Is there a way, to attach a standard or custom handler to it?
Without a hack, I think you're going to be stuck here, I'm sorry to say. When you set the VB6 borderless properties, you inherently disable the control menu. The control menu (typically activated by right-clicking the title bar of a window or left-clicking the icon in the upper left) is what's displayed when you right-click a window in the task bar.
Now, if you're in the mood to hack, you might be able to "simulate" the behavior in such a way that the user doesn't know the difference. I got the idea from this message thread on usenet.
Basically, it sounds like you may be able to hack it by using two forms. One form is minimized right away, and becomes your "stub" in the task bar. The other form is the one you're currently designing (which we'll call the "main" form). The stub form is what actually loads and displays your main form.
The stub form isn't borderless, and must not deactivate the control menu. It is positioned off screen and at the smallest possible size. You'll respond to its form-level events, and then use those to communicate the appropriate behaviors to the borderless form.
That's the general gist of the hack. If I wasn't at work right now, I'd whip up a simple VB6 project and see if I could get it to work for you.