100% agreed with all points. Thanks.
2006/3/18, Robert May <rmay@...>:
> Reini Urban wrote:
> >Robert May wrote:
> >>Here's what I am proposing:
> >>(1) All windows/controls will gain the -acceptfiles option that will be
> >>used to set/unset the WS_EX_ACCEPTFILES extended style on the
> >>window/control (For those of you familiar with it, this is all that the
> >>Win32 DrapAcceptFiles() API does). This is a minor change to
> >>GUI_Options.cpp, and improves on the original implementation that only
> >>supported dropping for Window/DialogBox.
> > Great!
> >>(2) All Windows/Controls will gain the AcceptFiles() method to get/set
> >>the WS_EX_ACCEPTFILES extended style. Additionally, as this informatio=
> >>is available from the extended style, no additional storage is needed t=
> >>track a window's dragdrop state.
> > The only minor inconvenience is with the naming.
> > DragDrop object
> > -acceptfiles option
> > DropFiles ( =3D> WM_DROPFILES ) NEM or OEM eventname
> > GetDroppedFiles() vs. DragQueryFile() methods
> > I'd rather prefer -dropfiles over -acceptfiles, so that the supported
> > event has the same name as the option which declares it.
> > On the other side, WS_EX_ACCEPTFILES and DrapAcceptFiles() is also
> > established on the API side.
> I'm not wedded to the API call names, particularly when we have methods
> that don't directly map to the API. As I think about it I propose the
> following public API:
> - flag to turn on/off WS_EX_ACCEPTFILES will be -acceptfiles - we have
> precedent for naming style options like this.
> - the callback will be -onDropFiles and <window_name)_DropFiles, as
> that's what it is called today, and matches precedent for naming events
> (cf. WM_DROPFILES)
> - For consistency the module will be named Win32::GUI::DropFiles. This
> better reflects the actual functionality, and avoids a namespace clash
> with the existing Loft Win32::GUI::DragDop
> - There will an AccepFiles() method on the window objects for
> getting/setting the WS_EX_ACCEPTFILES style. This is consistent with
> current naming conventions (e.g. -dialogui/DialogUI()) Note that we can
> also use $win->Change(-acceptfiles =3D> 0|1) for setting.
> >>(2) The DropFiles callback which is already supported for all
> >>windows/controls (handling WM_DROPFILES) will change it's callback
> >>parameter from the current HDROP integer to a Win32::GUI::DropFiles
> >>object. This is a minor change to GUI_MessageLoops.cpp
> This change will only be made if our new Win32::GUI::DropFiles module is
> loaded. If it is not, then the existing callback with a drophandle will
> be used - this gives us the backwards compatibility we are looking for.
> >>(3) The Win32::GUI::DropFiles object will expose the following methods:
> >>- GetDroppedFiles, which will return:
> >> in scalar context the number of files dropped
> >> in list context a list of dropped file names
> >>- GetDroppedFile, which will take a zero-based index for
> >> the dropped file, and will return the file name
> > hmm.
> Why hmm? We need to provide some sort of iterator access so that the
> user can efficiently deal with large numbers of dropped files, rather
> than only being able to get a list of all the files. Perhaps a proper
> interator api would be better with a Reset() and GetNextFile[Name]()
> >>- GetDropPos, which will return:
> >> in scalar context whether the drop was in the client or
> >> non-client area of the window
> > Is this possible at all?
> Yes, it's the return value of DragQueryPos
> >> in list context the position of the mouse when the drop
> >> occurred in client co-ordinates
> >>It should be possible to write GetDroppedFiles() so that code written t=
> >>use the GUI Loft's GetDroppedFiles() method will continue to work,
> >>without modification.
> > That was my idea also.
> > The only problem is with the naming, DragQueryFile() vs
> > GetDroppedFile()
> This is no longer necessary, and deals with the naming conflict for
> > It's only the Loft which introduced the name GetDroppedFiles().
> > WINAPI declares DragQueryFile and DragQueryPoint. I would like to stay
> > with the WINAPI names.
> I'm not wedded to the API calls, but the module will also provide the
> following (non-?)public APIs:
> - direct mapping of the win32 api. Included only for completeness.
> Win32::GUI::DropFiles::DragQueryFile(HDROP, [ITEM])
> - mapping of the win32 api DragQueryFile api: if called with only the
> HDROP parameter, returns a count of the dropped files; if called with
> the HDROP and ITEMS parameter returns the filename for ITEM
> - returns a list of 3 scalars: X-pos, y-pos and (non-)client flag
> - direct mapping of the win32 api
> > GetDropPos: Doesn't DragQueryPoint report the position
> > while being dragged also? So it's not only after being dropped.
> No. We only get the HDROP handle after the drop occurs (in the
> WM_DROPFILES message) You need to implement a full COM IDropTarget
> interface and use RegisterDragDrop() api to get this sort of
> functionality. You'd then get DragEnter, DragOver, DragLeave and Drop
> callbacks, and more control over what the cursor looks like etc. A
> future enhancement to this module? :-)
> > The idea behind the high level GetDroppedFiles() is to automatically
> > cleanup the object.
> I don't agree with this - that might have been the intention of the
> original DragDrop module, but is not mine.
> > I'm not sure if this is a good idea, since perl
> > automatically will DESTROY the HDROP, and a DragQueryPoint afterward
> > will fail. So please back this idea out.
> Right - calling DragFinish makes the HDOP handle invalid, and so it
> can't be re-used later. My implementation of GetDroppedFiles() does not
> call DragFinish(), and I have DrapFinish called in the object's DESTORY
> method, so that it gets called when the object goes out of scope
> (typically at the end of the DropFiles callback).
> This approach is problematic, as if the DropFiles module is not loaded,
> then there is no DESTROY method, and DragFinish never gets called,
> resulting in a memory leak. Note that this is no worse than today's
> situation, where if you set the WS_EX_ACCEPTFILES style and don't
> explicitly call DragFinish() somewhere in the callback we have a leak.
> Really the WM_DROPFILES handling code should call DragFinish() and
> return 0. This is easy enough to implement, but does mean that object
> passed to the callback is only valid during the callback. As I will be
> checking to see if our module is loaded before deciding whether to pass
> a HDROP handle, or Win32::GUI::DropFiles object to the callback I
> propose that if the module is not loaded, we'll explicitly call
> DragFinish when the callback returns. From what I can see there's no
> harm in calling it if it's already been called during the callback, and
> doing this will solve the memory leak problem.
> >>(4) I intend to write all this as a separable module, with its own DLL
> >>for the new Win32 api calls required. Whilst there is some overhead of
> >>this approach I want to use it as a proof of concept, as it gives the
> >>following advantages:
> >>- the code is separable, and hence more maintainable
> >>- there will be no overhead (in fact a saving) for applications that
> >>don't need the functionality (GUI.dll and GUI.pm are already way too bi=
> >>- I believe that writing tests for smaller bits of functionality will
> >>prove significantly easier. (although I'm not sure this is a good examp=
> >>- It will be possible to 'dual-life' modules like this, allowing for
> >>fixes/upgrades outside the normal Win32::GUI release cycle
> > Ok. I like that idea and I did this with CustomDraw.pm
> > The basic event and the object property getters do work without
> > use Win32::GUI::CustomDraw;
> > You only need to use it - and import a lot of autoloaded methods and
> > helper constants - if you want to call a method, primarly for setting a
> > value, and need some constants.
> > Maybe we should export the CustomDraw XS calls to a seperate DLL which
> > should be imported by the user or AUTOLOAD'ed.
> > But it's by far not that big as the convenience methods in the perl par=
> Probably - but I haven't had a chance to look at your CustomDraw code yet=
> > For DragDrop:
> > The WM_DROPFILES event should work without use Win32::GUI::DragDrop;
> > But calling the methods might require it.
> Without Win32::GUI::DropFiles it'll work as today, passing a HDROP
> handle. If you use Win32::GUI::DropFiles; then you'll get an object in
> the callback and acceess to the methods.
> > Or AUTOLOAD it based on the object name.
> > Same with the Brush and DC maybe.
> >>If it proves to be the wrong approach, then it will be easy to fold the
> >>changes back into the main GUI.xs and GUI.pm files. If it proves good,
> >>the over time I hope to move other less used features out of GUI.pm and
> >>Additionally I want to look at putting more of the code than we might
> >>usually in perl rather than XS so that we can keep the DLL sizes small
> >>and (in the future) take better advantages of AUTOLOADing little used
> > OwnerDraw, NotifyIcon and such.
> > Yes.
> NotifyIcon I certainly have on my list of candidates. I haven't thought
> much beyond that, but I am hopeful that a restructuring like this might
> reduce GUI.xs and GUI.pm to more manageable sizes. I also want to
> experiment with moving a lot of the per-control methods from XS back
> into perl. There are many methods implemented in XS that do a single
> call to SendMessage. By moving them back into perl I don't think we'll
> see much of a performance hit (there's still one 'thunk' between perl
> and XS, which I suspect to be the largest time overhead), and will be
> able to move all such methods to be AUTOLOADed, so we only take compile
> time and memory hits if we use them in our apps.
I believe XS code is much more performant than simple perl wrappers
over SendMessage. Memory and time wise. I'll do some research.
Our only problem is probably size and memory, time is good enough.
At least for me.
Maintainencewise simple perl pm's are much easier to
handle, even if the worst time performance is on searching and opening
of those extra files.
Pulling them only optionally in via AUTOLOAD is a good argument,
even for deployed exe's with embedded dll and pm modules.
Which is Jeremy's point.
> > PS:
> > Note that I did some wrong guards with the new NotifyIcon members.
> > It should be compiler dependent and not IE dependent, when the shell
> > version call will fail.
> I haven't looked yet. It's not really compiler dependent, but SDK
> version dependent. I'm using VC6++ compiler on Win98, but with the
> latest SDK headers, and I don't get hit by any problems. I may make it
> a requirement to have the lastest headers, so that I can remove much of
> the work-arounds from GUI.h (or perhaps just move it all to separate
> header files) ... something to think about in the future.