-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for drag images and drop descriptions #6576
Add support for drag images and drop descriptions #6576
Conversation
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
…he target window and add support for drop description icons and text. *Narrow the scope to drop targets with support for drop icons and text. *Maintain the default DropTarget behavior with a last flag. *If the application specifies a DropIcon greather than DropIcon.Invalid (default), display the drag image, drop icon, and text specified in the DragEventArgs. *Add a DragDropHelper class to interface with the Shell's drag-image manager and provide methods to get and set the drop description. *Add a DragDrop functional test form to WinformsControlsTest with files for testing drag-and-drop operations.
f5c2c90
to
1ce2618
Compare
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/System.Windows.Forms.Primitives/src/Interop/Interop.CLSID.cs
Outdated
Show resolved
Hide resolved
…t DragDropHelper.SetDragImage().
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include the cursor offset.
src/System.Windows.Forms/src/System/Windows/Forms/DragDropHelper.cs
Outdated
Show resolved
Hide resolved
@weltkante appreciate your feedback as well here. I think this will remove the need to expose interfaces publicly as discussed here: #457. @willibrandon, We decided to take this forward and will work with you to get this ready for API review board. |
I have one last part I'd like to include in this draft before taking it to the API review board and would like a chance to first get some feedback from the team. Specifically, specifying the drag image bitmap itself when calling DoDragDrop(). I'll try to get this last part pushed this evening. The only thing holding me up is I need to implement a function to copy an STGMEDIUM since I've previously been using |
Thanks for the ping, looks promising, though I'm surprised this approach works considering WinForms doesn't implement SetData on its DataObject. I'll have a closer look at the proposed implementation and API over the next few days. |
@weltkante - The IDataObject::SetData and IDataObject::GetData changes will be included in my next push, hopefully this evening. |
Add support for the drag-and-drop helper object calls to IDataObject::SetData and IDataObject::GetDataHere.
@weltkante - I've pushed what I believe is the last major part required for this issue. Some further work needs to be done in order to add in the support for |
This comment was marked as outdated.
This comment was marked as outdated.
src/System.Windows.Forms/src/System/Windows/Forms/DataObject.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.CopyStgMedium.cs
Outdated
Show resolved
Hide resolved
-Check for null drag image bits
-Attempts to access shell objects from a multithreaded apartment fail with error E_NOINTERFACE.
-These are causing other tests to fail so they are going to detention.
I am moving this out of draft. @willibrandon , can you resolve conflict when you get chance. @JeremyKuhne Can you take a final look here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks for all of your hard work and patience!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved the conflict
@willibrandon, as FYI, this will be merged for the Preview 7 release. |
@willibrandon , can you open a new issue for this and we can track the discussion there to figure out ? |
* Allow drop targets to display a drag image while the cursor is over the target window and add support for drop description icons and text. *Narrow the scope to drop targets with support for drop icons and text. *Maintain the default DropTarget behavior with a last flag. *If the application specifies a DropIcon greather than DropIcon.Invalid (default), display the drag image, drop icon, and text specified in the DragEventArgs. *Add a DragDropHelper class to interface with the Shell's drag-image manager and provide methods to get and set the drop description. *Add a DragDrop functional test form to WinformsControlsTest with files for testing drag-and-drop operations. * Tweak the drop description icon names. * Cleanup feedback from RussKie * Build fix * Add IDragSourceHelper2 interface, SHDRAGIMAGE structure, and implement DragDropHelper.SetDragImage(). * Add the Control.DoDratgDrop API for specifying the drag image bitmap. Add support for the drag-and-drop helper object calls to IDataObject::SetData and IDataObject::GetDataHere. * Fix naming rule violation. * Implement a CopyDragDropStgMedium function for copying drag-and-drop storage mediums. * Remove unused DragDropHelper methods and add comments. * Add CopyDragDropStgMedium format validation and comments. * Hide the PictureBox default pointer on the test form. * Cleanup feedback from RussKie. * Tweak DragDropHelper return values. * Fix the cursor from getting stuck and fix the cursor offset. * Fix memory leak and add additional formats. * Allow the application to specify the drag image bitmap via GivefeedbackEventArgs. * Add more comments. * Cleanup some feedback from welkante. Implement change detection for drop descriptions in DragEnter and DragOver. Make DragOver symmetrical in API with DragEnter. * Reject SetData calls which have a non-NULL target device pointer. * Add an internal drag and drop format class to hold related private formats and storage mediums. Encapsulate the logic to copy the storage medium when retrieving the private formats. Include a finalizer and call ReleaseStgMedium to free copied storage mediums marked for release. * Handle when the caller retains ownership of the storage medium and make a copy. * Reject incompatible storage medium types in IDataObject::SetData. * Debug assert null target device pointer. * Cleanup the return and let it fall through like previously. * Add the Control.DoDragDrop API surface. -Optimize the drop description change detection in DropTarget. -Add drag image change detection in DropSource. -Set and get the DropTarget state to help support controls which have a complex internal structure. -Make DragEnter/DragOver more symmetrical. -Handle the DragOver edge case when a new drag image is specified in DropSource.GiveFeedback. -Handle the DragOver edge case when the previous DropTarget state was not DragEnter. * Add the ToolStripItem.DoDragDrop API surface. -Add drag image and drop description support for ToolStrip. -Add a ToolStrip control to the test form for testing drag and drop operations. * Add drag image and drop description support for RichTextBox. * Add a RichTextBox demo to load DragAccept.rtf on DragDrop. * Optimize drop description changes in DragLeave and Drop. * Add a comment regarding IDataObject::GetData and when the Windows drag image manager requests formats that are not currently present in the data object. * Improve the RichTextBox and ToolStrip demos. * Add the InShellDragLoop format. * Add data object support for CF_INDRAGLOOP. -Set the flag to true when setting the initial drag image. -Use the flag to check whether the data object is in a drag-and-drop loop. -Set the flag to false when the data has been dropped. * Use Marshal.ReleaseComObject instead of Marshal.FinalReleaseComObject. * Finish adding support CFSTR_INDRAGLOOP. * Add support for dynamic addition of data during the drag loop through SetData. -Expand the scope of CopyDragDropStgMedium to copy all storage medium types and rename it to CopyStgMedium. * Fix the timing of the flag. * Clean up the comments and code. * Free the DragDropFormat storage mediums after they are no longer in use. * Fix the timing of the drag loop flag. * Give the DragDropFormat appropriate method names. * Set InDragLoop in GiveFeedback for good measure. * Wrap the drag loop in a try finally and reset InDragLoop. * Resolve nullable and mark members as static errors. * Track the DropSource last target handle using IDropSourceNotify::DragEnterTarget If a target has already been entered, call IDropTargetHelper::DragEnter to effectively display new drag images that are set during GiveFeedback. * Cleanup feedback from dotnet api review Align the names of DropImageType with Windows terminology including using the term Image over Icon. - Default -> Invalid - NoDropIcon -> NoImage DragEventArgs - DropIcon -> DropImageType - Insert -> MessageReplacementToken - Mark the Message* properties as nullable. GiveFeedbackEventArgs - Match DoDragDrop bitmap nullability and mark the bitmap non-nullable. * Fix typo * Check if the drop description values specified are valid * Review feedback * Review feedback * Move CopyMedium to the DragDropFormat class and rename it to CopyData * Remove unnecessary return and cleanup the demo * Review feedback * Update DropSource CCW to include support for IDropSourceNotify * Review feedback * Fix MessageReplacementToken conditional * Be explicit about the entry indexes * Review feedback * Wrap the methods calls in a try/catch and return HResult of exception * Remove the unnecessary checks in ToolStripDropTargetManager * Simplify the checks in DropTarget * Simplify the checks in RichTextBox.OleCallback * Simplify the checks in DropSource * Review feedback, first round * Remove the unused using * Better way of checking the incoming data object * Have the designer generate the code * Put the update drag image logic in its own method * Review feedback * Review feedback, second round * Add the <returns> tag and describe the DragDropEffects return value * Add GiveFeedbackEventArgs remarks * Review feedback * Review feedback and encapsulate the event argument equality logic * Review feedback * Fix duplicate symbols * Review feedback * Add DragDropFormat unit tests * Supply named arguments for boolean parameters * Cleanup the data source and variable name * Add DragContext test data and generalize the tests * Add DragDropHelper unit tests * Skip test DragDropHelper_SetDragImage_ReturnsExptected Results in Fatal error 0xC0000005 on Windows_x86 Debug and Release when executed from the command line. * Add DragEventArgsTests for newly added properties * Add GiveFeedbackEventArgs unit tests * Add unit tests that verify thrown exceptions * Add UI integration test for DragEnter * Fix the fatal error on x86 * Tune up the test * Unskip the skipped tests * Fix the hard coded delay * Fix SetDragImage tests -Check for null drag image bits * Review feedback * Check for illegal cross-thread calls in DragDropHelper -Attempts to access shell objects from a multithreaded apartment fail with error E_NOINTERFACE. * Skip the problem tests -These are causing other tests to fail so they are going to detention. * Drag two items in the UI test Co-authored-by: Jeremy Kuhne <[email protected]>
* Allow drop targets to display a drag image while the cursor is over the target window and add support for drop description icons and text. *Narrow the scope to drop targets with support for drop icons and text. *Maintain the default DropTarget behavior with a last flag. *If the application specifies a DropIcon greather than DropIcon.Invalid (default), display the drag image, drop icon, and text specified in the DragEventArgs. *Add a DragDropHelper class to interface with the Shell's drag-image manager and provide methods to get and set the drop description. *Add a DragDrop functional test form to WinformsControlsTest with files for testing drag-and-drop operations. * Tweak the drop description icon names. * Cleanup feedback from RussKie * Build fix * Add IDragSourceHelper2 interface, SHDRAGIMAGE structure, and implement DragDropHelper.SetDragImage(). * Add the Control.DoDratgDrop API for specifying the drag image bitmap. Add support for the drag-and-drop helper object calls to IDataObject::SetData and IDataObject::GetDataHere. * Fix naming rule violation. * Implement a CopyDragDropStgMedium function for copying drag-and-drop storage mediums. * Remove unused DragDropHelper methods and add comments. * Add CopyDragDropStgMedium format validation and comments. * Hide the PictureBox default pointer on the test form. * Cleanup feedback from RussKie. * Tweak DragDropHelper return values. * Fix the cursor from getting stuck and fix the cursor offset. * Fix memory leak and add additional formats. * Allow the application to specify the drag image bitmap via GivefeedbackEventArgs. * Add more comments. * Cleanup some feedback from welkante. Implement change detection for drop descriptions in DragEnter and DragOver. Make DragOver symmetrical in API with DragEnter. * Reject SetData calls which have a non-NULL target device pointer. * Add an internal drag and drop format class to hold related private formats and storage mediums. Encapsulate the logic to copy the storage medium when retrieving the private formats. Include a finalizer and call ReleaseStgMedium to free copied storage mediums marked for release. * Handle when the caller retains ownership of the storage medium and make a copy. * Reject incompatible storage medium types in IDataObject::SetData. * Debug assert null target device pointer. * Cleanup the return and let it fall through like previously. * Add the Control.DoDragDrop API surface. -Optimize the drop description change detection in DropTarget. -Add drag image change detection in DropSource. -Set and get the DropTarget state to help support controls which have a complex internal structure. -Make DragEnter/DragOver more symmetrical. -Handle the DragOver edge case when a new drag image is specified in DropSource.GiveFeedback. -Handle the DragOver edge case when the previous DropTarget state was not DragEnter. * Add the ToolStripItem.DoDragDrop API surface. -Add drag image and drop description support for ToolStrip. -Add a ToolStrip control to the test form for testing drag and drop operations. * Add drag image and drop description support for RichTextBox. * Add a RichTextBox demo to load DragAccept.rtf on DragDrop. * Optimize drop description changes in DragLeave and Drop. * Add a comment regarding IDataObject::GetData and when the Windows drag image manager requests formats that are not currently present in the data object. * Improve the RichTextBox and ToolStrip demos. * Add the InShellDragLoop format. * Add data object support for CF_INDRAGLOOP. -Set the flag to true when setting the initial drag image. -Use the flag to check whether the data object is in a drag-and-drop loop. -Set the flag to false when the data has been dropped. * Use Marshal.ReleaseComObject instead of Marshal.FinalReleaseComObject. * Finish adding support CFSTR_INDRAGLOOP. * Add support for dynamic addition of data during the drag loop through SetData. -Expand the scope of CopyDragDropStgMedium to copy all storage medium types and rename it to CopyStgMedium. * Fix the timing of the flag. * Clean up the comments and code. * Free the DragDropFormat storage mediums after they are no longer in use. * Fix the timing of the drag loop flag. * Give the DragDropFormat appropriate method names. * Set InDragLoop in GiveFeedback for good measure. * Wrap the drag loop in a try finally and reset InDragLoop. * Resolve nullable and mark members as static errors. * Track the DropSource last target handle using IDropSourceNotify::DragEnterTarget If a target has already been entered, call IDropTargetHelper::DragEnter to effectively display new drag images that are set during GiveFeedback. * Cleanup feedback from dotnet api review Align the names of DropImageType with Windows terminology including using the term Image over Icon. - Default -> Invalid - NoDropIcon -> NoImage DragEventArgs - DropIcon -> DropImageType - Insert -> MessageReplacementToken - Mark the Message* properties as nullable. GiveFeedbackEventArgs - Match DoDragDrop bitmap nullability and mark the bitmap non-nullable. * Fix typo * Check if the drop description values specified are valid * Review feedback * Review feedback * Move CopyMedium to the DragDropFormat class and rename it to CopyData * Remove unnecessary return and cleanup the demo * Review feedback * Update DropSource CCW to include support for IDropSourceNotify * Review feedback * Fix MessageReplacementToken conditional * Be explicit about the entry indexes * Review feedback * Wrap the methods calls in a try/catch and return HResult of exception * Remove the unnecessary checks in ToolStripDropTargetManager * Simplify the checks in DropTarget * Simplify the checks in RichTextBox.OleCallback * Simplify the checks in DropSource * Review feedback, first round * Remove the unused using * Better way of checking the incoming data object * Have the designer generate the code * Put the update drag image logic in its own method * Review feedback * Review feedback, second round * Add the <returns> tag and describe the DragDropEffects return value * Add GiveFeedbackEventArgs remarks * Review feedback * Review feedback and encapsulate the event argument equality logic * Review feedback * Fix duplicate symbols * Review feedback * Add DragDropFormat unit tests * Supply named arguments for boolean parameters * Cleanup the data source and variable name * Add DragContext test data and generalize the tests * Add DragDropHelper unit tests * Skip test DragDropHelper_SetDragImage_ReturnsExptected Results in Fatal error 0xC0000005 on Windows_x86 Debug and Release when executed from the command line. * Add DragEventArgsTests for newly added properties * Add GiveFeedbackEventArgs unit tests * Add unit tests that verify thrown exceptions * Add UI integration test for DragEnter * Fix the fatal error on x86 * Tune up the test * Unskip the skipped tests * Fix the hard coded delay * Fix SetDragImage tests -Check for null drag image bits * Review feedback * Check for illegal cross-thread calls in DragDropHelper -Attempts to access shell objects from a multithreaded apartment fail with error E_NOINTERFACE. * Skip the problem tests -These are causing other tests to fail so they are going to detention. * Drag two items in the UI test Co-authored-by: Jeremy Kuhne <[email protected]>
Before I forget, thank you for the opportunity to work on this. It has been an incredible learning experience for me and everyone here has been so helpful and welcoming. Early on I was terrified that I wouldn’t be able to figure this one out. While getting the drag images from Explorer to display on WinForms drop targets was trivial, specifying the drag image bitmap itself from a drag source was a much more daunting task for me. When I got it working the first time I almost had a heart attack and started screaming OMG. This has been an awesome experience for me, thank you. |
Congratulation! That’s WinForms team for you 🏅. Also, take care of your heart ;) |
Thank you so much for your efforts and your patience! |
Allow drop targets to display the drag image while the cursor is over the target and add support for setting drop descriptions.
Allow drag sources to specify the drag image bitmap.
Resolves #5884.
Proposed changes
Maintain the current default
DropTarget
behavior. By default, do not display the drag image and drop description.Add a new public enumeration;
DropImageType
.DragEventArgs
properties;DropImageType
,Message
, andMessageReplacementToken
.During the
DragEnter
event, if the application specifies aDragEventArgs.DropImageType
greater thanDropImageType.Invalid
, display the drag image and drop description.Add 3 new
GiveFeedbackEventArgs
properties;DragImage
,CursorOffset
, andUseDefaultDragImage
.DoDragDrop
methods.During the
DoDragDrop
method or theGiveFeedback
event, if the application specifies aDragImage
bitmap, setCFSTR_INDRAGLOOP
to true and initialize the drag-image manager by callingIDragSourceHelper2.InitializeFromBitmap()
.Load and retrieve the arbitrary private data formats used by the drag-and-drop helpers and manage the storage and release of the related storage mediums using a private
DragDropFormat
class.Add an internal
DragDropHelper
class to manage the retrieval of theIDragSourceHelper2
andIDropTargetHelper
interface pointers and expose the methods necessary to set and display the drag image and drop description.Add a drag and drop functional test form to the WinformsControlsTest project with files for testing drag and drop operations.
Customer Impact
Regression?
Risk
Video
DropTarget_DragImageDropDescription.mp4
DragSource_DragImageDropDescription.mp4
ToolStrip_DragImageDropDescription.mp4
WinForms_DragImageDropDescription.mp4
Test methodology
Accessibility testing
TODO
Test environment(s)
Microsoft Reviewers: Open in CodeFlow