Handling wpf drop of external programs - c#

I'm trying to fiddle with an idea, and one big concept is dropping programs, bookmarks, etc. I have what I believe to be the gist of it but I'm not receiving any information
private void Border_Drop(object sender, DragEventArgs e)
{
FileInfo[] files = (FileInfo[])e.Data.GetData(DataFormats.FileDrop);
foreach (FileInfo file in files)
{
Writer.Text += file.FullName;
}
}
Though my textblock is never populated? I'd like to get all the properties of File such as FullName, Name, Extension, DirectoryName, etc.
Any pointers on where to go from here? I've been trying to read the MSDN of the event but nothing is coming up, and I've searched stackoverflow and nothing is working for my case scenario.

One possible reason is that you have attached the event handler to the wrong control. Try attaching the event handler to the Form, or if that does not work, the textblock.
I would also highly recommend doing some debugging. Place a breakpoint in the event handler to see if it is called, and if so, what happens in it.

WPF has two different routed event handling mechanisms: bubbling and tunneling. Bubbling is the "normal" way to do it, and tunneling is when you see all those PreviewThis and PreviewThat in the event name. It's possible, that another control has aready marked the event as handled, and so you don't see it in your event handler.
If you need documentation for WPF drag and drop, read this
If you need some really custom, really low level stuff on this subject, you can also read up on Object Linking and Embedding This is probably how drag-and-drop is implemented in Word so that you can drag images and Excel tables into Word documents and they will display natively. But to use this you will probably need to use some Win32 API calls which is a bit of a bummer.

Related

Remove and later re-add all event handlers associated with a groupbox in C# winforms

Is there a way to get the collection of handlers associated with a groupbox in C# winforms?
For the cases the checked statuses need to be changed programatically (not by the user), I need to turn off the handlers so other parts of the program do not fire. It is tedious to do this by hand for many handlers.
Is there a working code version of this pseudocode that does not work below?
foreach(Control C in parent.groupBox1.Controls)
{
C.disableHandlers()
}
//change controls handlers would have interfered with
foreach(Control C in parent.groupBox1.Controls)
{
C.enableHandlers()
}
It is possible to use some crazy reflection code to do this, but you don't want to do that because you'll invariably run into "well I still want to keep this event just not the others".
I recommend making a class that contains a list of add-listener delegates and a list of remove-listener delegates, and then iterate through and execute each delegate at the appropriate times.

How can I pass data through a DragDrop event?

I have very little experience making my own events. I'm currently using forms and controls to handle events, so I'm trying to stick to the WinForm way of dealing with events.
WinForm controls already have their own events. Since events are made with a certain delegate type, I have to match the delegate signature in the methods I use to handle what goes on during an event. As far as I can tell, this means I have to take in two parameters in my event handlers: a source Object and an EventArgs.
I'm trying to figure out how to pass various information between controls through DragDrop related events. I've been able to find various code snippets online for different situations, but I'd like to have a better understanding of how the information is actually passed around.
When it comes to DragDrop events in particular, it seems my information will be passed through a DataObject. That, in turn, is passed as a parameter to the DragDrop.DoDragDrop method.
This is where my understanding starts to diminish. In most examples I've seen, it looks like some sort of data format is specified. The data format itself is of type string. Usually the data format is passed along with the data into the DataObject.
What is this data format doing? Is it just showing the type of the data involved? I've seen examples where the data format was tested, and various actions took place depending on what the data format had been. Couldn't you just do a typeof(YourData) to check for the type? I don't understand how a data format is useful.
http://msdn.microsoft.com/en-us/library/ms741842.aspx
In the above link, the first example shows a DataObject being created with no data format being specified. It explains that the data format is automatically chosen and that your object is converted by default.
Can you just pass any object into the DataObject? Then when the DragDrop event takes place on the target control, can that control access the methods and fields of the object passed? Or will the object be converted into some other form by the DataObject? How about various structures?
I've also done some drag and dropping from a Windows explorer icon to my forms. I was able to get the icon's file path with some example code I found. It also used a data format.
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
SUMMARY:
I'm trying to get an understanding of how data is passed through WinForm events. I don't understand some of what I've seen in various DragDrop examples. I understand that data is somehow stored in various formats, and that there is a way to extract that data. I don't understand what a data format is used for. I don't understand exactly what sorts of data can be transferred through a DataObject. My understanding of EventArgs in general is fairly lacking.
Feel free to comment on anything I've mentioned here. If I stated something incorrectly, point it out. Anything that will help me understand this subject better is appreciated.
EDIT:
I decided to explain where I plan to go with this. Maybe someone can use what I'm trying to do as a way to explain some of what I asked.
I have a form that contains a certain type of control. I'm trying to make the placement of the controls highly customizable and dynamic. Whenever another control is added to the form by the user, every control is automatically repositioned to keep things orderly.
I'm currently trying to allow the user to drag a control around the Form to resposition it. Wherever the user decides to drop the control, all of the other controls will move out of the way to make room for the move control.
If I'm going to be able to move the dragged control and all the other controls on the form properly, I need to be able to get certain information from the dragged control. The main data that would need to be passed through the events would take the form of a Location property that uses a System.Drawing.Point structure.
Here's something to give you an idea of how it's done.
First drop two panels on a Form, and set their colors to two different colors.
public Form1()
{
InitializeComponent();
panel1.MouseDown += new MouseEventHandler(panel1_MouseDown);
panel2.AllowDrop = true;
panel2.DragEnter += new DragEventHandler(panel2_DragEnter);
panel2.DragDrop += new DragEventHandler(panel2_DragDrop);
}
void panel1_MouseDown(object sender, MouseEventArgs e)
{
panel1.DoDragDrop(panel1, DragDropEffects.Move);
}
void panel2_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetData(typeof(Panel)) != null) e.Effect = DragDropEffects.Move;
}
void panel2_DragDrop(object sender, DragEventArgs e)
{
Panel p = sender as Panel;//Not needed in this case. Could just write panel2.
Panel dropped = (Panel)e.Data.GetData(typeof(Panel));
dropped.Location = p.PointToClient(new Point(e.X, e.Y));
p.Controls.Add(dropped);
}
Then drag panel1 onto panel2.
I think this problem should not be solved using drag&drop. Drag&drop is meant as a way for multiple applications to exchange data. If the data you are dragging is only meaningful for the current process, don't use drag&drop.
You can just use a field (for example, a field on the instance of the containing Form) to store all the data you need.
Just to say the obvious: Drag&drop is not a way to drag around controls. You need a lot of custom logic for that, anyway. It's not like the built-in features of dnd would help you here.

C# (Windows Forms) Input Output Keyboard and Mouse States

How to get keyboard and mouse input (what buttons are currently pressed) && also how to send output (make the mouse click at a specific position in another program). If you could also add comments on what different things do and why you use them would be terrific :D
Cheers! //Daniel
http://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library
This article is quite helpful. It even includes code for a cool macro recorder.
This may not be a very good solution but bad as i am (didnt understand how to use the other ones that were suggested) i chose the siple way out... i used using Microsoft.Xna.Framework.Input; after getting the xna framework reference, then i simply went ahead and did keyboardstate currentkeyboard = keyboard.getstate :) same with mouse
.NET only has .NET controls (forms, buttons,etc) based mouse/keyboard hooking built in, so to programmatically respond to those events outside your .NET controls you need a global event hook that can intercept mouse and keyboard activity from anywhere in windows.
HowTo use one keyboard/mouse hook dll to perform the functionality you are requesting (the ability to respond programmatically to mouse/keyboard events globally):
Download "Gma.UserActivityMonitor.dll" from: global mouse/keyboard kooks in c#
Place this dll in C:\Windows\System32
In your project, include a reference (from VS, add...reference and browse to the dll)
In your project code, add "using Gma.UserActivityMonitor;"
In your code, declare these event consumers:
HookManager.MouseMove += HookManager_MouseMove;
HookManager.KeyPress += new KeyPressEventHandler(HookManager_KeyPress);
Here are some method stubs that can be raised when the mouse/keyboard events occur:
private void HookManager_MouseMove(object sender, EventArgs e)
{
}
private void HookManager_KeyPress(object sender, EventArgs e)
{
}
Hope this helps, this is how I did it when I needed to consume global mouse and keyboard events in my code.

C# : filesystemwatcher class

i have a question about the moving file event on filesystemwatcher class , i`d like to stop the moving of file or edit it when the moving file event arises for a certain file , is that possible to handle inside the moving event ?
No, there is no way to stop someone moving or renaming a file using the FileSystemWatcher class.
If you look, none of the event arguments passed by the events on the FileSystemWatcher class have a Cancel property. Also, the fact that the class is simply called a Watcher is a bit of a clue.
You might consider using Access Control Lists to make sure someone cannot delete a file (since a move is really just a copy/delete). Or perhaps you could try opening a FileStream on the file so that you have it locked.
You cannot directly "cancel" the operation by means of the event handler. You would have to provide a compensating operation to programatically "undo" any changes you want undone.
You only receive the events after the fact has happened. It's a mere notification, not an event you'd have to approve. This can also be guessed from the missing Cancel or Handled property in the FileSystemEventArgs (as opposed to, for example, the KeyEventArgs) class.
You can detect a move and try to move the file back, based on the OldFullPath property of the RenamedEventArgs you receive.
This might however be confusing to your users or to other software. And try not to end up in an infinite loop, where you move the file back and forth every time you receive the event.

AxAcroPDF swallowing keys, how to get it to stop?

The AxAcroPDF swallows all key-related events as soon as it gets focus, including shortcuts, key presses, etc. I added a message filter, and it doesn't get any key-related messages either. It's a COM component, could that be relevant?
Is there any way to catch these before the control starts swallowing them?
Hans is correct, the Acrobat Reader spawns two child AcroRd32 processes which you have no direct access to from within your managed code.
I have experimented with this and you have three viable options:
You can create a global system hook, and then look for and filter out / respond to WM_SETFOCUS messages sent to your child AcroRd32 windows. You can accomplish some of this from within C# by using a wrapper library, such as the one here: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx
You also need to identify the correct processes as there may be more than one instance of your application, or other instances of AcroRd32. This is the most deterministic solution, but because your application will now be filtering messages sent to every single window in existence, I generally don't recommend this approach because then your program could negatively affect system stability.
Find an alternate PDF viewing control. See this answer for a few commercial components: .net PDF Viewer control , or roll your own: http://www.codeproject.com/KB/applications/PDFViewerControl.aspx
Find an acceptable hack. Depending on how robust your application needs to be, code such as the following may be suitable (it was suitable for my case):
DateTime _lastRenav = DateTime.MinValue;
public Form1()
{
InitializeComponent();
listBox1.LostFocus += new EventHandler(listBox1_LostFocus);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
axAcroPDF1.src = "sample.pdf"; //this will cause adobe to take away the focus
_lastRenav = DateTime.Now;
}
void listBox1_LostFocus(object sender, EventArgs e)
{
//restores focus if it were the result of a listbox navigation
if ((DateTime.Now - _lastRenav).TotalSeconds < 1)
listBox1.Focus();
}
I might finally have a ridiculously simple answer. So far in testing this is working.
Having suffered from this problem for quite some time and having built a complex system of each custom control recording which of them last had focus and using a timer to flip focus back (when acropdf grabbed it) I revisited this problem and read a great number of answers (looking for recent solutions). The information gleaned helped me with the idea.
The idea is to disable the (acropdf) control whilst it is loading as in the following example (code reduced for clarity)
AxAcroPDF_this.Enabled = False
AxAcroPDF_this.src = m_src
Then on a timer, after say 1 second.
AxAcroPDF_this.Enabled = True
Basically the idea is to tell Windows not to let users use the acropdf control until allowed, so asking Windows to prevent it from getting focus (because users are not allowed in there).
So far this is holding up, I will edit this if anything changes. If it doesn't work completely for you then maybe the idea points into a useful direction.
It is an out-of-process COM component, that's the problem. Completely in violation of Windows SDK requirements as laid out in SetParent(). Once its window gets the focus, the message loop in the acroread.exe process gets all the messages, your message filter cannot see any messages anymore.
Technically it is fixable by using SetWindowsHookEx() to inject a DLL into the process and monitor messages with WH_GETMESSAGE. But you can't write such a DLL in the C# language.
Major suck, I know. There never seems to be any lack of it with that program.
For some reason Tim's answer, disabling the AxAcroPDF control directly, didn't work in my case. The Leave event on the previously-selected Textbox would never fire, either.
What is working is nesting the AxAcroPDF control inside of a disabled GroupBox. Since the users of my application need to only see the PDF, not interact with it, the GroupBox's Enabled property is set to False in the designer.

Categories

Resources