From: Julian Smart Date: Thu, 8 Apr 1999 19:36:00 +0000 (+0000) Subject: Added candidate wxDragImage implementation for wxMSW X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/7cf83330863f93c6f9772f50ea974b53ec576e79 Added candidate wxDragImage implementation for wxMSW git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2071 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/dragimag.h b/include/wx/dragimag.h new file mode 100644 index 0000000000..dbbce924d2 --- /dev/null +++ b/include/wx/dragimag.h @@ -0,0 +1,23 @@ +#ifndef _WX_DRAGIMAG_H_BASE_ +#define _WX_DRAGIMAG_H_BASE_ + +#if defined(__WXMSW__) +#ifdef __WIN16__ +#include "wx/generic/dragimag.h" +#else +#include "wx/msw/dragimag.h" +#endif +#elif defined(__WXMOTIF__) +#include "wx/generic/dragimag.h" +#elif defined(__WXGTK__) +#include "wx/generic/dragimag.h" +#elif defined(__WXQT__) +#include "wx/generic/dragimag.h" +#elif defined(__WXMAC__) +#include "wx/generic/dragimag.h" +#elif defined(__WXSTUBS__) +#include "wx/generic/dragimag.h" +#endif + +#endif + // _WX_DRAGIMAG_H_BASE_ diff --git a/include/wx/msw/dragimag.h b/include/wx/msw/dragimag.h new file mode 100644 index 0000000000..a7a1fd0988 --- /dev/null +++ b/include/wx/msw/dragimag.h @@ -0,0 +1,189 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dragimag.h +// Purpose: wxDragImage class: a kind of a cursor, that can cope +// with more sophisticated images +// Author: Julian Smart +// Modified by: +// Created: 08/04/99 +// RCS-ID: $Id$ +// Copyright: (c) Julian Smart +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_DRAGIMAG_H_ +#define _WX_DRAGIMAG_H_ + +#ifdef __GNUG__ +#pragma interface "dragimag.h" +#endif + +#include "wx/bitmap.h" +#include "wx/icon.h" +#include "wx/cursor.h" +#include "wx/treectrl.h" +#include "wx/listctrl.h" + +/* + To use this class, create a wxDragImage when you start dragging, for example: + + void MyTreeCtrl::OnBeginDrag(wxTreeEvent& event) + { +#ifdef __WXMSW__ + ::UpdateWindow((HWND) GetHWND()); // We need to implement this in wxWindows +#endif + + CaptureMouse(); + + m_dragImage = new wxDragImage(* this, itemId); + m_dragImage->BeginDrag(wxPoint(0, 0), this); + m_dragImage->Move(pt, this); + m_dragImage->Show(this); + ... + } + + In your OnMouseMove function, hide the image, do any display updating required, + then move and show the image again: + + void MyTreeCtrl::OnMouseMove(wxMouseEvent& event) + { + if (m_dragMode == MY_TREE_DRAG_NONE) + { + event.Skip(); + return; + } + + // Prevent screen corruption by hiding the image + if (m_dragImage) + m_dragImage->Hide(this); + + // Do some updating of the window, such as highlighting the drop target + ... + +#ifdef __WXMSW__ + if (updateWindow) + ::UpdateWindow((HWND) GetHWND()); +#endif + + // Move and show the image again + m_dragImage->Move(event.GetPosition(), this); + m_dragImage->Show(this); + } + + Eventually we end the drag and delete the drag image. + + void MyTreeCtrl::OnLeftUp(wxMouseEvent& event) + { + ... + + // End the drag and delete the drag image + if (m_dragImage) + { + m_dragImage->EndDrag(this); + delete m_dragImage; + m_dragImage = NULL; + } + ReleaseMouse(); + } +*/ + +/* + Notes for Unix version: + Can we simply use cursors instead, creating a cursor dynamically, setting it into the window + in BeginDrag, and restoring the old cursor in EndDrag? + For a really bog-standard implementation, we could simply use a normal dragging cursor + and ignore the image. +*/ + +/* + * wxDragImage + */ + +class WXDLLEXPORT wxDragImage: public wxObject +{ + DECLARE_DYNAMIC_CLASS(wxDragImage) +public: + + // Ctors & dtor + //////////////////////////////////////////////////////////////////////////// + + wxDragImage(); + wxDragImage(const wxBitmap& image, const wxCursor& cursor = wxNullCursor, const wxPoint& hotspot = wxPoint(0, 0)) + { + m_hImageList = 0; + Create(image, cursor); + } + wxDragImage(const wxIcon& image, const wxCursor& cursor = wxNullCursor, const wxPoint& hotspot = wxPoint(0, 0)) + { + m_hImageList = 0; + Create(image, cursor); + } + wxDragImage(const wxString& str, const wxCursor& cursor = wxNullCursor, const wxPoint& hotspot = wxPoint(0, 0)) + { + m_hImageList = 0; + Create(str, cursor); + } + wxDragImage(const wxTreeCtrl& treeCtrl, wxTreeItemId& id) + { + m_hImageList = 0; + Create(treeCtrl, id); + } + wxDragImage(const wxListCtrl& listCtrl, long id) + { + m_hImageList = 0; + Create(listCtrl, id); + } + ~wxDragImage(); + + // Attributes + //////////////////////////////////////////////////////////////////////////// + + // Operations + //////////////////////////////////////////////////////////////////////////// + + // Create a drag image from a bitmap and optional cursor + bool Create(const wxBitmap& image, const wxCursor& cursor = wxNullCursor, const wxPoint& hotspot = wxPoint(0, 0)); + + // Create a drag image from an icon and optional cursor + bool Create(const wxIcon& image, const wxCursor& cursor = wxNullCursor, const wxPoint& hotspot = wxPoint(0, 0)); + + // Create a drag image from a string and optional cursor + bool Create(const wxString& str, const wxCursor& cursor = wxNullCursor, const wxPoint& hotspot = wxPoint(0, 0)); + + // Create a drag image for the given tree control item + bool Create(const wxTreeCtrl& treeCtrl, wxTreeItemId& id); + + // Create a drag image for the given list control item + bool Create(const wxListCtrl& listCtrl, long id); + + // Begin drag. hotspot is the location of the drag position relative to the upper-left + // corner of the image. + bool BeginDrag(const wxPoint& hotspot, wxWindow* window); + + // End drag + bool EndDrag(wxWindow* window); + + // Move the image: call from OnMouseMove. Pt is in window client coordinates if window + // is non-NULL, or in screen coordinates if NULL. + bool Move(const wxPoint& pt, wxWindow* window); + + // Show the image + bool Show(wxWindow* window); + + // Hide the image + bool Hide(wxWindow* window); + + // Implementation + //////////////////////////////////////////////////////////////////////////// + + // Returns the native image list handle + inline WXHIMAGELIST GetHIMAGELIST() const { return m_hImageList; } + +protected: + WXHIMAGELIST m_hImageList; + wxCursor m_cursor; + wxPoint m_hotspot; + wxPoint m_position; +}; + +#endif + // _WX_DRAGIMAG_H_ diff --git a/src/msw/dragimag.cpp b/src/msw/dragimag.cpp new file mode 100644 index 0000000000..8588617c27 --- /dev/null +++ b/src/msw/dragimag.cpp @@ -0,0 +1,253 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: dragimag.cpp +// Purpose: wxDragImage +// Author: Julian Smart +// Modified by: +// Created: 08/04/99 +// RCS-ID: $Id$ +// Copyright: (c) Julian Smart +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "dragimag.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if defined(__WIN95__) + +#ifndef WX_PRECOMP +#include +#include "wx/setup.h" +#include "wx/window.h" +#include "wx/dcclient.h" +#endif + +#include "wx/log.h" +#include "wx/intl.h" + +#include "wx/msw/dragimag.h" +#include "wx/msw/private.h" + +#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) +#include +#endif + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxDragImage, wxObject) +#endif + +wxDragImage::wxDragImage() +{ + m_hImageList = 0; +} + +wxDragImage::~wxDragImage() +{ + if ( m_hImageList ) + ImageList_Destroy((HIMAGELIST) m_hImageList); + m_hImageList = 0; +} + + +// Attributes +//////////////////////////////////////////////////////////////////////////// + + +// Operations +//////////////////////////////////////////////////////////////////////////// + +// Create a drag image from a bitmap and optional cursor +bool wxDragImage::Create(const wxBitmap& image, const wxCursor& cursor, const wxPoint& hotspot) +{ + if ( m_hImageList ) + ImageList_Destroy((HIMAGELIST) m_hImageList); + m_hImageList = 0; + + UINT flags = 0; + bool mask = TRUE; // ? + if ( mask ) + flags |= ILC_MASK; + + m_hImageList = (WXHIMAGELIST) ImageList_Create(image.GetWidth(), image.GetHeight(), flags, 1, 1); + + HBITMAP hBitmap1 = (HBITMAP) image.GetHBITMAP(); + HBITMAP hBitmap2 = 0; + if ( image.GetMask() ) + hBitmap2 = (HBITMAP) image.GetMask()->GetMaskBitmap(); + + int index = ImageList_Add((HIMAGELIST) m_hImageList, hBitmap1, hBitmap2); + if ( index == -1 ) + { + wxLogError(_("Couldn't add an image to the image list.")); + } + + m_cursor = cursor; // Can only combine with drag image after calling BeginDrag. + m_hotspot = hotspot; + + return (index != -1) ; +} + +// Create a drag image from an icon and optional cursor +bool wxDragImage::Create(const wxIcon& image, const wxCursor& cursor, const wxPoint& hotspot) +{ + if ( m_hImageList ) + ImageList_Destroy((HIMAGELIST) m_hImageList); + m_hImageList = 0; + + UINT flags = 0; + bool mask = TRUE; // ? + if ( mask ) + flags |= ILC_MASK; + + m_hImageList = (WXHIMAGELIST) ImageList_Create(image.GetWidth(), image.GetHeight(), flags, 1, 1); + + HICON hIcon = (HICON) image.GetHICON(); + + int index = ImageList_AddIcon((HIMAGELIST) m_hImageList, hIcon); + if ( index == -1 ) + { + wxLogError(_("Couldn't add an image to the image list.")); + } + + m_cursor = cursor; // Can only combine with drag image after calling BeginDrag. + m_hotspot = hotspot; + + return (index != -1) ; +} + +// Create a drag image from a string and optional cursor +bool wxDragImage::Create(const wxString& str, const wxCursor& cursor, const wxPoint& hotspot) +{ + wxFont font(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); + + long w, h; + wxScreenDC dc; + dc.SetFont(font); + dc.GetTextExtent(str, & w, & h); + + wxMemoryDC dc2; + dc2.SetFont(font); + wxBitmap bitmap((int) w, (int) h); + dc2.SelectObject(bitmap); + + dc2.SetBackground(* wxWHITE_BRUSH); + dc2.Clear(); + dc2.DrawText(str, 0, 0); + + dc2.SelectObject(wxNullBitmap); + + return Create(bitmap, cursor, hotspot); +} + +// Create a drag image for the given tree control item +bool wxDragImage::Create(const wxTreeCtrl& treeCtrl, wxTreeItemId& id) +{ + if ( m_hImageList ) + ImageList_Destroy((HIMAGELIST) m_hImageList); + m_hImageList = (WXHIMAGELIST) TreeView_CreateDragImage((HWND) treeCtrl.GetHWND(), (HTREEITEM) (WXHTREEITEM) id); + return TRUE; +} + +// Create a drag image for the given list control item +bool wxDragImage::Create(const wxListCtrl& listCtrl, long id) +{ + if ( m_hImageList ) + ImageList_Destroy((HIMAGELIST) m_hImageList); + POINT pt; + pt.x = 0; pt.y = 0; + m_hImageList = (WXHIMAGELIST) ListView_CreateDragImage((HWND) listCtrl.GetHWND(), id, & pt); + return TRUE; +} + +// Begin drag +bool wxDragImage::BeginDrag(const wxPoint& hotspot, wxWindow* WXUNUSED(window)) +{ + wxASSERT_MSG( (m_hImageList != 0), "Image list must not be null in BeginDrag."); + + bool ret = (ImageList_BeginDrag((HIMAGELIST) m_hImageList, 0, hotspot.x, hotspot.y) != 0); + + wxASSERT_MSG( (ret), "BeginDrag failed."); + + if (!ret) + return FALSE; + + if (m_cursor.Ok()) + { + // First add the cursor to the image list + int cursorIndex = ImageList_AddIcon((HIMAGELIST) m_hImageList, (HICON) m_cursor.GetHCURSOR()); + + wxASSERT_MSG( (cursorIndex != -1), "ImageList_AddIcon failed in BeginDrag."); + + if (cursorIndex != -1) + { + ImageList_SetDragCursorImage((HIMAGELIST) m_hImageList, cursorIndex, m_hotspot.x, m_hotspot.y); + } + } + + ::ShowCursor(FALSE); + + return TRUE; +} + +// End drag +bool wxDragImage::EndDrag(wxWindow* WXUNUSED(window)) +{ + wxASSERT_MSG( (m_hImageList != 0), "Image list must not be null in EndDrag."); + + ImageList_EndDrag(); + + ::ShowCursor(TRUE); + + return TRUE; +} + +// Move the image: call from OnMouseMove. Pt is in window client coordinates if window +// is non-NULL, or in screen coordinates if NULL. +bool wxDragImage::Move(const wxPoint& pt, wxWindow* window) +{ + wxASSERT_MSG( (m_hImageList != 0), "Image list must not be null in Move."); + + // TODO: what coordinates are these in: window, client, or screen? + bool ret = (ImageList_DragMove( pt.x, pt.y ) != 0); + + m_position = pt; + + return ret; +} + +bool wxDragImage::Show(wxWindow* window) +{ + wxASSERT_MSG( (m_hImageList != 0), "Image list must not be null in Show."); + + HWND hWnd = 0; + if (window) + hWnd = (HWND) window->GetHWND(); + + bool ret = (ImageList_DragEnter( hWnd, m_position.x, m_position.y ) != 0); + + return ret; +} + +bool wxDragImage::Hide(wxWindow* window) +{ + wxASSERT_MSG( (m_hImageList != 0), "Image list must not be null in Hide."); + + HWND hWnd = 0; + if (window) + hWnd = (HWND) window->GetHWND(); + + bool ret = (ImageList_DragLeave( hWnd ) != 0); + + return ret; +} + +#endif + // __WIN95__ +