How to move an UI automation element to a different location? - c#

I have a C#.NET app where I am able to find a AutomationElement at a particular point using FromPoint function.
Now I want to manipulate that AutomationElement so that I can move it to a different location, resize it etc.
For moving and resizing , I thought that I can use SetWindowPos Window API function but that requires the handle(an IntPtr) of the target window. Using the AutomationElement's "Current" property, i can read the NativeWindowHandle(an int) of it.
Since Control is also a window, I passed this int value as window handle to the SetWindowPost function hoping that it would do my job.
But the code is not working.
Kindly suggest me a way to do this.

What's the type of element you want to move - a top-level window, or an item within a window? Also, is this a type of item that a user could move around using mouse or keyboard? UIAutomation is only supposed to allow you to manipulate the UI consistent with what a regular user could do - you can't use it to move the controls around on a dialog, for example.
The official way to move things in UIAutomation is to see if the element supports the Transform Pattern, and then use the Move or Resize methods to move it appropriately. I think this is mostly implemented only on top-level windows, not sure about how widely it is implemented on other controls - you can use UISpy/Inspect to check your target UI.
If the element is a HWND, you could also get the NativeWindowHandle property - which is the underlying HWND, but you'll need to convert it to IntPtr first - and then use it in Win32 APIs. This only works for actual HWND items, though, not for say items in a listview.

Related

Adding an overlay to the active window

I am trying to figure out if there is a way in C# to add such an overlay to another window's Title bar. I am trying to make a program that monitors your keyboard input and will show prompts based if a certain word is typed. I already have everything else working, but this.
One way is to hook into the global Message Procedure with SetWindowsHookEx(WH_GETMESSAGE, ..., NULL) then in GetMsgProc() you check for WM_PAINT messages, and if the HWND is the currently top window, comparing message->hwnd with result of GetTopWindow(NULL), after that you can add your custom GDI Drawing code.
Detailed example of the Hooking DLL code can be found in the answer for this Question
How to draw graphics/text on top of another application

How can I write my own ContextMenu? C#

I feel quite limited by the default ContextMenuStrip, as it only can contain buttons, and no Controls.
I was wondering that for a long time, and I already tried it, using forms, but it never really worked out.
I already have I idea on how to set the whole thing up, with events and items. The only problem I have is the paint method.
When you open a ContextMenu (ContextMenuStrip) you can set its position on the mouse cursor, and it will be there, even if that means that it goes beyond the active form. (So I can't use the Controls Class as inheritance, as they can only draw themself as a part of a form.
Now I thought to use the Form Class as a base for my ContextMenu, but those where placed on the screen randomly.
So what I actually need is a class (or something similar) that can draw itself, without problems, and can be placed accurately on the screen.
Any hint would be nice, thanks.
Greg the Mad
Your first statement is false -- you can have a TextBox or a ComboBox in a ContextMenuStrip.
MSDN ToolStripComboBox
MSDN ToolStripTextBox
From the designer there is a small drop-down arrow when your mouse is in the "Type Here" box (sometimes hard to click) that will allow you to change the type.
If you are looking to allow for any type of control to be displayed in a top down fashion inside of a container to be positionable... you could always make a custom control using FlowLayoutPanel. With it's properties FlowDirection=TopDown and WrapContents=False to keep a vertical approach. This will handle your "menu" basics and your new control can expose whichever events you wish from each Control. You will have to handle the logic of showing the panel and positioning with it's Location property as well.
I forgot to address the issue with drawing outside of the parent form. Notice that ContextMenus are smart and when they reach a boundary of their parent they draw away from it. You should logically be able to draw in the correct direction (Up/Down or Left/Right) from any right mouse click. Per your attempt with a Form, set StartPosition=Manual then prior to calling Show() or ShowDialog() set it's Location property respective to the X and Y parameters provided in the event args of MouseClick.

Building a MVVM 3D Editor Application -> Getting Mouse Position?

In my 3d editor application, I want to be able to click on and move a scene's entities (meshes, lights, cameras, etc). To do that, I imagine that I need to get the current mouse position relative to my Direct3d view and somehow give it to my ViewModel. How would I go about doing that, considering that my app is built with the MVVM pattern?
Additional Info: The Direct3d renderer is from a C++ DLL and we're using an HwndHost to place it inside our WPF app. It has a WndProc which I imagine I could use to handle mouse messages there but I'd rather avoid it if at all possible.
Thanks!
The best solution I found is to use an attached behavior. In the control that serves as the placeholder to the HwndHost I set an attached property, like
b:MouseBehavior.LeftClick="{Binding DoSomeActionCommand}"
where MouseBehavior receives the control and sets mouse events on it.
It works well for me.
InputManager.Current.PrimaryMouseDevice is probably your best bet.
you can get the mouse position with
Mouse.Position( RelativeToObject ); // get the mouse pos relative to an object
Mouse.Position( null ); // get the mouse pos relative to the whole screen
if thats not good enough, you can use Win32 calls.

Implement sticky overlays in .NET

I'm looking for a nice way to render overlays over a native Windows form not owned by myself preferably using a library available for .NET (WinForms, GTK#, ...). Precisely, I'd like to display a few labels or text boxes at a given location on the window.
Device Context & System.Drawing: What I'm currently doing is drawing directly onto the other windows' device context, which causes flickering, as parts of the other application are redrawn in unpredictable intervals. I therefore would have to catch its WM_PAINT event using hook magic, but that's actually not as far down as I'd like to go unless there's no simpler way.
Transparent window overlay with visible child labels: another technique I tried was creating a Windows.Forms.Form with the other windows' size, using TransparencyKey to make only the children visible. This seems pretty hard to get correct, as I don't want the window to be the upper-most one but only exactly one Z-level above the foreign window. The upside would be, that I could add more behaviour to it, as I could actually handle click events, etc.
How would you implement it / deal with the problems in the two techniques described above?
Definitely go with the transparent window approach as that should be simpler to implement. Creating a transparent form is very easy. You already know how to use the TransparenyKey to get the background to not drawn. Also remove the border from the window and remove the min/max/close buttons so you do not have any chrome showing.
Create your window as owned by the window of interest and it will always be on top of the target and act like a modeless dialog. I.e. it is visible only when the owning window is visible.
Thanks for your answer, but I'm still a little confused. How exactly would you set the owner of a window to anything not owned by your own application? I guess that's not even possible when the other application is unmanaged, is it?
Edit:
I now got a little step closer. The example code is in Boo.
[DllImport("user32.dll", SetLastError: true, CharSet: CharSet.Auto)]
public def SetParent(child as IntPtr, parent as IntPtr):
pass
def createAttachedForm(parentHandle as IntPtr):
f = Form()
f.Text = "My overlay"
f.Show()
SetParent(f.Handle, parentHandle)
Application.Run(f)
Now only the TransparencyKey thing doesn't seem to work. Instead the form is completely invisible when the value is set.
Setting the owner of a form can be done with
Form.Show(IWin32Window w)
where w exposes the Handle to the parent window.

What WPF C# Control is similar to a CWnd in C++?

What would be the best WPF control in C# (VS 2008) that you can place on a form that would allow you to do drawing similar to the "Paint" function for the CWnd class in C++? Also, that could display bitmaps, have a scroll bar, and the ability to accept user inputs (ie. MouseMove, Button Clicks, etc...). Basically all the functionality of a CWnd in a control on a WPF form?
The UIElement is the lowest level element that supports input and drawing. Although, using WPF, you really have to do a lot less manual drawing. Are you sure that you need to do this? Also, the scroll bar will never be inherit in your element. If you need scrolling behavior, just wrap your element in a ScrollViewer.
UIElement is the place to start and OnRender is the method to override.
Be warned that WPF is heavily geared toward composing UI as opposed to the WM_PAINT ways of Win32. Unless you are creating new low level primitives there is almost always a more productive alternative.

Categories

Resources