WinAPI / WPF: Set system cursor only for application - c#

I have an application whose UI is custom rendered with a theme. I also want to add new non-default-cursors (like the resize cursors when the user intends to resize the window) to match that theme.
With the WinAPI function SetCursor I am only able to change the default pointer for the application, but this is not enough, so I looked up SetSystemCursor which works just fine. Problem is: The latter version changes the cursors system-wide permanently, but I only want them to be changed for my application only.
I thought about copying the previous cursors before I do the SetSystemCursor and re-set them at application exit, but even when I implement a terminate handler it may not be called if the process e.g. just crashes. Also the cursors would still be changed system-wide as long as the application is running.
Specifically for the resize-cursors, I could just drop the window style, make a borderless window, and render/implement the resizing grips and logic myself (then I could just hook the mouse-over events), but that is really just my last resort - I'd rather like to know if it is possible achieve my goal before I do this cumbersome task...
For anyone who is interested: The UI is rendered with WPF, but WPF doesn't provide this functionality either (again, they have it, but just for the default pointer). It's no concern for me to use the WinAPI or other "low-level" calls if I have to, but at the moment it seems there are none that are fitting my needs :(
So if anybody knows how to change the other system cursors (not the default pointer) in WPF or WinAPI just for my application without having to implement custom cursor-logic to my window just for that, you would make my day.

I don't know how to implement this in WPF, but if you want to set the cursor to something other than default, then your window procedure should handle the WM_SETCURSOR message.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648382(v=vs.85).aspx

Related

VS 2013 Quick Find loses focus when switching to my application - how do I preserve/restore it programmatically?

I have whipped up a C# clipboard application that stores multiple 'clippings' for later use. I use low-level keyboard hooks to pop open my application's window(s) on command. When the window is closed (or a clipping is double-clicked), it is supposed to paste the selected clipping into the last active window (the window prior to my application's window). I use low-level WINAPI methods to determine the last active application, snag its handle, and then return focus to it before simulating a Ctrl+V keystroke to paste.
This typically works except in one very unique scenario: I am in a WPF application project, Quick Finding in a XAML file, the cursor automatically switches to the body text, not the Quick Find textbox, and pastes it there. It seems to have something to do with the loss of focus/activation, as it moves the cursor whenever I activate another window, regardless of my own application's running.
VB files, C# files, what have you, and XAML opened in WinForm projects do not steal the Quick Find focus when switching between the VS2013 application and my own; upon returning to the last active application, the text pastes into the Quick Find box.
Only the XAML in WPF application projects gives me this problem.
So far. I know it is a fringe case, but I expect to run into more. This program is meant to be used in a coding environment and it's pretty important that it be able to handle these kinds of scenarios.
I've tried getting the internal control handle using code from http://www.codeproject.com/Articles/34752/Control-in-Focus-in-Other-Processes, so that I can return the focus to it, but it seems that the handle for the body text and the handle for the Quick Find text box are the same.
A partial solution is found in: How do I prevent the original form from losing focus when I show another form? The popup window I use is navigated primarily through my low-level shortcuts, and therefore has no need of explicit activation.
Using the mouse on it or any of my other windows (as I expect my users will sometime), will cause it to gain activation and circumvent this fix. However, it's such a fringe case it doesn't seem to matter. Hopefully this helps anyone in a similar situation (if not necessarily specifically this one).

WPF element hosted in ElementHost not redrawing correctly

I'm writing a program to implement COM component in C#. This component provides a UI component too. In the interest of making it easy to implement future additions to the component, I decided to write the UI in Xaml using WPF and wrapping it in an ElementHost control to provide the handle back to to the COM consumer.
Here's where this gets interesting. The element is being hosted in a win32 tab control. The first time the tab is selected, it loads fine. Switching to another tab and coming back causes it to not draw the component correctly. If I move the mouse through it, it'll draw the TextBox elements, but it'll never redraw the whole UserComponent.
I've tried every possible solution I've seen suggested, from changing the height/width values of the component to putting the HwndTarget in SoftwareOnly rendering mode.
I'm not sure what to try at this point, so suggestions are welcome. I'd really like to do this without using Windows Forms as the future maintainers of this aren't the best programmers and it's a lot easier to tell them to write up a Xaml file with data bindings than manually lay out a form and set the values in the code-behind.
Haven't met such problem yet.
Try to force refresh or focus (methods) to the hosting wrapper or HwndSource when switching to the hosting tab.

Is there a way to ask about the status of a drag operation while it is in progress?

I know that when a drag/drop operation is completed, upon receiving a MouseUp or Esc key event, it returns an enum that indicates what happened (Move, Copy, None, etc.) My question is this: is there a way to send back status information to the form/control that initiated the drag event, while it is going on?
The use case is as follows (think Visual Studio-esque layout manager for all of this): I am writing a layout/window managing component that allows regions of the layout to be dragged around. I use a transparent form to paint a semi-transparent overlay that changes based on where the mouse is dragging over, a la the preview overlay that appears when dragging windows around in Visual Studio.
Another motivation is that the serialization process I describe is relatively resource intensive, and I'd prefer not to do it if the dragging is all going to occur within the same process/window. So, if there was a way to lazily serialize only when an actual "drop" in another window happens, that would probably make all the difference in usability.
What I want to do is enable dragging between different windows or even different instances of the application. I've already plumbed out the serialization code and everything, but the issue is that, when I drag a chunk of layout into another window, the first window doesn't have any way of knowing that the mouse is now over another instance of the application, which is more than capable of painting its own overlay. So, the original overlay hangs around like an idiot and my program looks like crap.
Is there any way for me to pass along some kind of callback or is there any message or property I can listen for/poll during a drag operation that will tell me if my mouse pointer is over a region that can accept its data? Please don't make me resort to listening for the CursorChanged event, I've already lost too much self respect using reflection to hack around weird wpf/winforms dragging interop bugs. If anyone could suggest a clean resolution for this problem I would be extremely grateful.
Additionally, if anyone could point me to any favorite sites which describe how to go about doing reeeeally funky things with drag and drop, it would be appreciated, as I've found there is quite a lack of really nitty gritty information available about dragging. Usual things like custom cursors and the like are okay, but I'm probably more interested in Win32 black arts and the like.
UPDATE:
I actually just found out about the GiveFeedback event a second ago, came back to my question, and there it was. Huge facepalm moment. However, since I've got you here, what about my second question: is there any way to lazily load the information only when it encounters a valid target? Could I somehow implement my own IDataObject or do things get marshaled righ when the mouse leaves the form? GiveFeedback provides me only with whether there's a valid target under the cursor, but doesn't let me change what data is being dragged...
ANOTHER UPDATE:
Is there any way to determine the source of a drag operation? That is, when my control receives a DragEnter message, how can I tell if the source of the drag is my own control or a foreign one? I know I can hackishly encode it by messing with the AllowedEffects property, but is there any more direct route?
Check out the GiveFeedback event (there's a nice article here) - that sounds to me to be exactly what you're after.

Minimise any program to system tray

Hey, I am trying to make a program that minimises any program to the system tray instead of normally minimising it. Is this possible? I have been looking around on google but cant find anything.
Icons in the system tray are called "Notification Icons".
To do this to your own application, If your using WinForms you can use the NotifyIcon class to display icons in the system tray. Then all you have to do it set the window to not be displayed in the task bar.
If you're using WPF there isn't a replacement, you still have to use the old WinForms NotifyIcon class, check out this MSDN sample for more information on this.
If you want to hide another app, what you need to do is use API calls to make the changes to the state of the applications window.
You can use FindWindow to get a handle to the window you want to hide, then you can use GetWindowLong to get the windows state. Then you need to remove the WS_EX_APPWINDOW flag from the state and use the SetWindowLong method to apply the new style, this will remove it from the task bar. You can then use the Get/SetWindowState methods to find out the state of the window and hide/minimise it.
You still just need to use the NotifyIcon class to display your own icon in the systray.
Good luck with all of that. It's not something I've tried personally, but I've used all these method calls in other ways. If you haven't done API stuff from C# before you might find you need to do a bit of googling to figure out your DllImports for the version API methods. Shouldn't be anything too hard though.
Crazyd22 has found a codeproject article that uses a slightly different set of API methods but achieves pretty much the same effect. (See comments below.)

Change the icon of the window of the minimize, close and maximize

Simple question. How can I change the icons of the close, minimize, maximize buttons. Can I do this in Winforms and WPF?
These Icons, the caption, and the border on your window are all drawn while processing the WM_NCPAINT message. So, the way you take over drawing this is by handling this message.
But you don't have access to the state information about the icons (i.e. which button you should draw in it's pressed state because the user is currently clicking on it.). You dont even know where exactly the mouse handling code thinks these icons are.
So to take over non-client paint, you also need to take over non-client mouse handling, and the whole problem just snowballs until you've written thousands of lines of code and your window still doesn't behave quite right when the user tries to drag it, etc.
And that's in unmanaged code, in managed code (C#/.Net) this is even harder because you also have to do interop to get to some of the APIs you need to use.
So the answer is: Yes its possible, but its harder in WinForms and WPF than it is in C++, and those that have attempted it are all bald now.
The real answer is that you shouldn't do this. Users expect all applications to work and look the same. Making them try an figure out what spiffy new icon you use means minimize is likely to make them unhappy.
Doing this isn't difficult but it is a lot of work - you have to basically replace the window frame and handle everything yourself, there is a lot of functionality in the default window frame you have to rewrite - you also have to write different code for Vista/7 with Aero enabled.
In WPF you use the various techniques in http://blogs.msdn.com/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx
In WinForms you use the same basic techniques but I don't know of a page that summarizes all the details like the link above.
In wpf, you can set WindowStyle="None" for your Window and then set a custom TitleBar for that, with minimize, maximize and close button. I have done this earlier. You need to do some event handling to perform minimize, maximize, close, drag etc.
Yes, you have to create your own window style. Refer to FluidKit, GlassWindows for example.
If you want to control the look of those buttons, you'll have to create your own. This is one value of using Windows features to write windows applications (they come with a standard look and feel).

Categories

Resources