Hallo Leute,
ich habe ein fremdes Control in meiner Anwendung, welches Drop von Bildern unterstützt. D.h. der Benutzer kann ein beliebiges Bitmap in das Control reinziehen und fallen lassen.
Meine Frage:
Wie kann ich dies mit Hilfe von C# machen? Also die Drop-Interaktion nachcoden!? Damit das Control denkt, es wäre der Benutzer der das Bild gedropped hat 🙂
Währe cool wenn jemand eine Idee hätte 🤔
Danke
Steffen
Jede Form und jedes Control hat Drag Events zb this.DragOver Damit müsste man das machen.Hab ich selber aber noch nich ausprobiert. Versuch ich jetzt auch mal 😁
edit : Hab grad rausgefunden man muss erst this.AllowDrop = true;
Grüß pdelvo
So ich habs jetzt hinbekommen.
Man kann auf das Programm ein Bild ziehen und es wird in einer PictureBox angezeigt :
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.MaximumSize = pictureBox1.Size;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
this.AllowDrop = true;
this.DragEnter += new DragEventHandler(Form1_DragOver);
this.DragDrop += new DragEventHandler(Form1_DragDrop);
}
void Form1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false);
if (FileList.Count() == 1)
{
FileInfo fi = new FileInfo(FileList[0]);
if (fi.Extension == ".gif" | fi.Extension == ".bmp" | fi.Extension == ".jpg" | fi.Extension == ".jpeg";)
{
pictureBox1.Image = Image.FromFile(FileList[0]);
}
}
}
else
e.Effect = DragDropEffects.None;
}
void Form1_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false);
if (FileList.Count() == 1)
{
FileInfo fi = new FileInfo(FileList[0]);
if (fi.Extension == ".gif" | fi.Extension == ".bmp" | fi.Extension == ".jpg" | fi.Extension == ".jpeg";)
{
e.Effect = DragDropEffects.Move;
}
}
}
else
e.Effect = DragDropEffects.None;
}
Hallo, danke für deine Mühe aber dass habe ich nicht gemeint.... darüber gibts genügend beispiele...
ich möchte über das Programm ein Drop auslösen mit einer bestimmten datei die ich aussuche... lies mal nochmal meinen ersten beitrag 😉
Gruß
Steffen
Edit: Du kannst doch jetzt mal probieren ein Bild über DragDrop reinzuladen ohne die maus zubenutzen...
Hab ich mich wol verlesen, das geht so:
void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
string path =Path.Combine(Environment.GetEnvironmentVariable("TEMP";) , "tempimage.jpg";);
try{
File.Delete(path);
}catch{}
pictureBox1.Image.Save(path);
DataObject obj = new DataObject(DataFormats.FileDrop,path);
obj.SetFileDropList(new System.Collections.Specialized.StringCollection() { path });
//pictureBox1.GiveFeedback += new GiveFeedbackEventHandler(pictureBox1_GiveFeedback);
pictureBox1.DoDragDrop(obj, DragDropEffects.Copy);
}
(Hab lange gebrauch bis es funktioniert hat)
Gruß pdelvo
hmm irgendwie ist es immer noch nicht dass was ich brauche...
nochmal:
ich möchte eine Bitmap-Datei von der Platte in ein Control in meinem Programm Dropen, das Control hat AllowDrop aktiviert und ist auch implementiert, da es manuell mit der Maus funktioniert... jetzt will ich dies automatisch über das Programm machen...
Meinst du jetzt sowas
Bitmap bmp = Bitmap.FromFile(@"A:\dresse\zum\File.bmp");
Dafür brauch man kein Drag 'N' Drop
Entweder du drückst dich falsch aus oder ich bin zu doof
Gruß pdelvo
Ich müsste wahrscheinlich die WM_DROPFILES verschicken oder? nur wie stelle ich das wParam zusammen 🤔http://msdn.microsoft.com/en-us/library/bb774303(VS.85).aspx
Es ist so, ich habe bei mir im Programm ein fremdes Control von einem anderem Hersteller (von welchem ich kein code habe), in einem Sonderfall, kann man in das Control nur per DragDrop ein Bild fallen lassen und ich möchte genau dies nachprogrammieren... verstehst du jetzt was ich meine?
Jetz versteh ich was du meinst.Bin aber leider überfragt.Wende dich mal an den Hersteller des Controls. Oder suche nochmal im Context also Control. ...
kann man dass hier irgenwie missbrauchen? http://www.codeproject.com/KB/dotnet/DataObjectEx.aspx?fid=987712&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2401357
In dem ersten Link hats wohl einer hinbekommen (Delphi)
http://www.delphipraxis.net/topic49148.html
http://groups.google.de/group/microsoft.public.platformsdk.shell/browse_frm/thread/5bbd1d67913ac2c7?hl=de&lr=&rnum=2&prev=/groups%3Fq%3Dsendmessage%2Bwm_dropfiles%26hl%3Dde%26lr%3D%26selm%3D03c301c3973d%25240433f8e0%2524a101280a%2540phx.gbl%26rnum%3D2
In deinem Link scheint es eher ander herum zu laufen.
die beiden seiten habe ich auch schon gelesen,
nur wie kriege ich das ganze in C# portiert?
So wie es aussieht geht es ja "nur" um GlobalAlloc, GlobalLock, PostMessage und GlobalFree. Das sind API methoden die du dir mit einem DLLImport holen kannst.
Dokumentation dazu dürfte sich in der MSDN und auf PInvoke.net finden lassen.
In der Regel sollte alles was du brauchst in irgendwelchen *.h Files in der Windows SDK rumliegen (Konstanten usw.). Einige Teile kannst du sicher auch aus dem Codeproject Artikel bemühen.
das schwierige dabei ist das zusammenstellen der Struktur DROPFILES
ich werde es mal probieren und dann den Versuch hier posten.
Ich kann mir aber nicht vorstellen, daß der Hersteller des externen Controls NUR die Möglichkeit per Drag&Drop vorgesehen hat. Es gibt sicherlich ein Property, das die Zuweisung vornimmt.
hier mein gescheiterter Versuch:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr GlobalAlloc(uint uFlags, int dwBytes);
[DllImport("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
static extern IntPtr GlobalFree(IntPtr hMem);
public const uint GMEM_FIXED = 0x0000;
public const uint GMEM_SHARE = 0x2000;
public const uint WM_DROPFILES = 0x0233;
public struct POINT
{
public int x, y;
public POINT(int p1, int p2)
{
x = p1;
y = p2;
}
}
public struct DROPFILES
{
public IntPtr pFiles;
public POINT pt;
public bool fNC;
public bool fWide;
}
string strPath = @"D:\test.bmp";
IntPtr hGlobal = IntPtr.Zero;
hGlobal = GlobalAlloc(GMEM_SHARE, strPath.Length + 2);
IntPtr ptrLock = GlobalLock(hGlobal);
POINT point;
point.x = 100;
point.y = 100;
DROPFILES oDropFiles;
oDropFiles.pFiles = ptrLock;
oDropFiles.fNC = false;
oDropFiles.fWide = false;
oDropFiles.pt = point;
System.Runtime.InteropServices.ComTypes.STGMEDIUM oMedium = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
oMedium.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_HGLOBAL;
oMedium.unionmember = ptrLock;
//Send Message with a file reference.
bool bSent = PostMessage((IntPtr)Cameras[iIndex].DisplayControl.Handle, WM_DROPFILES, oMedium, IntPtr.Zero);
bool bRet = GlobalUnlock(hGlobal);
GlobalFree(hGlobal);
man muss ja als wParam ein IntPtr übergeben, bloss wie komme ich an den Zeiger von STGMEDIUM?
man muss ja als wParam ein IntPtr übergeben, bloss wie komme ich an den Zeiger von STGMEDIUM?
System.Runtime.InteropServices.Marshal.StructureToPtr
"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)
Ich kann mir aber nicht vorstellen, daß der Hersteller des externen Controls NUR die Möglichkeit per Drag&Drop vorgesehen hat. Es gibt sicherlich ein Property, das die Zuweisung vornimmt.
Es gibt auch andere Möglichkeit eine Datei reinzuladen, bloß in einem bestimmten Sonderfall gehts es aus bestimmten Gründen nicht, es funktioniert dann nur per Drag&Drop.
EDIT:
neuer gescheiterter Versuch (danke an Khalid!)
string strPath = @"D:\test.bmp";
IntPtr hGlobal = IntPtr.Zero;
hGlobal = GlobalAlloc(GMEM_SHARE, strPath.Length + 2);
IntPtr ptrLock = GlobalLock(hGlobal);
POINT point;
point.x = 100;
point.y = 100;
DROPFILES oDropFiles;
oDropFiles.pFiles = ptrLock;
oDropFiles.fNC = false;
oDropFiles.fWide = false;
oDropFiles.pt = point;
System.Runtime.InteropServices.ComTypes.STGMEDIUM oMedium = new System.Runtime.InteropServices.ComTypes.STGMEDIUM();
oMedium.tymed = System.Runtime.InteropServices.ComTypes.TYMED.TYMED_HGLOBAL;
oMedium.unionmember = ptrLock;
IntPtr pM = Marshal.AllocHGlobal(Marshal.SizeOf(oMedium));
Marshal.StructureToPtr(oMedium, pM, false);
//Send Message with a file reference.
bool bSent = PostMessage((IntPtr)Cameras[iIndex].DisplayControl.Handle, WM_DROPFILES, pM, IntPtr.Zero);
bool bRet = GlobalUnlock(hGlobal);
GlobalFree(hGlobal);
Wie äußert sich das nicht funktionieren denn?
Evtl. ist POINT (100,100) nicht korrekt.
ich habe gerade noch dies gefunden:
http://forums.fanatic.net.nz/index.php?showtopic=18873
hab es auch probiert, nur kriege ich es nicht hin 🙁 da kommt nichts an...
Ich hab mal ein Testprojekt erstellt wo dass ganze drin ist.
die Message wird auf jedenfall generiert und verschickt (siehe WndProc), bloß löst es kein DragDrop-Event aus 🤔
habe ich da irgendwo einen Fehler?
Wenn jemand eine Lösung dafür hat, bin ich immer ganz ohr!
hab es zwar anders lösen können, aber über Dropfile wäre es viel eleganter gewesen.
Hat es noch niemand ausprobiert? X(
ich bin immer noch auf der Suche nach einer Lösung 🤔