PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/Samples/Extra/DragDrop/drop_source/main.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 346 lines | 238 code | 75 blank | 33 comment | 24 complexity | e675287567ab4eca389903290028622c MD5 | raw file
  1. module drop_source.main;
  2. /**
  3. The project implements IDropSource and initiates a Drag & Drop operation.
  4. It uses an Edit control and allows dragging text from one application to another.
  5. */
  6. import core.runtime;
  7. import core.stdc.stdlib;
  8. import core.stdc.string;
  9. import std.conv;
  10. import std.exception;
  11. import std.stdio;
  12. import std.string;
  13. pragma(lib, "comctl32.lib");
  14. pragma(lib, "ole32.lib");
  15. pragma(lib, "gdi32.lib");
  16. import core.sys.windows.objidl;
  17. import core.sys.windows.ole2;
  18. import core.sys.windows.winbase;
  19. import core.sys.windows.windef;
  20. import core.sys.windows.wingdi;
  21. import core.sys.windows.winuser;
  22. import core.sys.windows.wtypes;
  23. import utils.com;
  24. import drop_source.source;
  25. import drop_source.resource;
  26. import drop_source.data_object;
  27. import drop_source.enum_format;
  28. extern (Windows)
  29. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  30. {
  31. int result;
  32. void exceptionHandler(Throwable e)
  33. {
  34. throw e;
  35. }
  36. try
  37. {
  38. Runtime.initialize();
  39. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  40. Runtime.terminate();
  41. }
  42. catch (Throwable o)
  43. {
  44. MessageBox(null, o.toString().toStringz, "Error", MB_OK | MB_ICONEXCLAMATION);
  45. result = 0;
  46. }
  47. return result;
  48. }
  49. enum APPNAME = "IDropSource";
  50. HWND hwndMain;
  51. HWND hwndEdit;
  52. HINSTANCE hInstance;
  53. WNDPROC OldEditWndProc;
  54. int myWinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
  55. {
  56. enforce(OleInitialize(null) == S_OK);
  57. scope(exit)
  58. OleUninitialize();
  59. MSG msg;
  60. hInstance = hInst;
  61. InitMainWnd();
  62. CreateMainWnd();
  63. while (GetMessage(&msg, null, 0, 0))
  64. {
  65. TranslateMessage(&msg);
  66. DispatchMessage(&msg);
  67. }
  68. return 0;
  69. }
  70. void InitMainWnd()
  71. {
  72. WNDCLASSEX wc;
  73. wc.lpfnWndProc = &WndProc;
  74. wc.lpszClassName = APPNAME;
  75. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
  76. wc.hInstance = hInstance;
  77. RegisterClassEx(&wc);
  78. }
  79. void CreateMainWnd()
  80. {
  81. hwndMain = CreateWindowEx(0, APPNAME, APPNAME,
  82. WS_VISIBLE | WS_OVERLAPPEDWINDOW,
  83. CW_USEDEFAULT, CW_USEDEFAULT, 512, 200, null, null,
  84. hInstance, null);
  85. }
  86. extern (Windows)
  87. LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  88. {
  89. switch (msg)
  90. {
  91. case WM_CREATE:
  92. // create a child-window EDIT control
  93. hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
  94. WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL,
  95. 0, 0, 0, 0, hwnd, null, hInstance, null);
  96. // fixed-width font
  97. SendMessage(hwndEdit, WM_SETFONT, cast(WPARAM)GetStockObject(ANSI_FIXED_FONT), 0);
  98. // subclass the edit control so we can add drag+drop support to it
  99. OldEditWndProc = cast(WNDPROC) SetWindowLong(hwndEdit, GWL_WNDPROC, cast(LONG)&EditWndProc);
  100. SetFocus(hwndEdit);
  101. return TRUE;
  102. case WM_COMMAND:
  103. // react to menu messages
  104. switch (LOWORD(wParam))
  105. {
  106. case IDM_FILE_EXIT:
  107. CloseWindow(hwnd);
  108. return 0;
  109. case IDM_FILE_ABOUT:
  110. MessageBox(hwnd, "IDropSource Test Application\r\n\r\n"
  111. "Copyright(c) 2004 by Catch22 Productions\t\r\n"
  112. "Written by J Brown.\r\n\r\n"
  113. "Homepage at www.catch22.net", APPNAME, MB_ICONINFORMATION);
  114. return 0;
  115. default:
  116. }
  117. break;
  118. case WM_CLOSE:
  119. DestroyWindow(hwnd);
  120. PostQuitMessage(0);
  121. return 0;
  122. case WM_SIZE:
  123. // resize editbox to fit in main window
  124. MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  125. return 0;
  126. default:
  127. }
  128. return DefWindowProc(hwnd, msg, wParam, lParam);
  129. }
  130. //Subclass window-procedure for EDIT control
  131. extern (Windows)
  132. LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  133. {
  134. static BOOL fMouseDown = FALSE;
  135. static BOOL fDidDragDrop = FALSE;
  136. switch (msg)
  137. {
  138. case WM_KEYDOWN:
  139. // when ESCAPE is pressed clear the current selection
  140. if (wParam == VK_ESCAPE)
  141. ClearSelection(hwnd);
  142. break;
  143. case WM_LBUTTONDOWN:
  144. case WM_LBUTTONDBLCLK:
  145. // if the mouse is pressed when it is over a selection,
  146. // then start a drag-drop as soon as the mouse moves next
  147. if (MouseInSelection(hwndEdit, lParam))
  148. {
  149. fMouseDown = TRUE;
  150. fDidDragDrop = FALSE;
  151. SetCapture(hwnd);
  152. return 0;
  153. }
  154. break;
  155. case WM_SETCURSOR:
  156. // set the mouse cursor to an ARROW when it intersects the
  157. // current selection, or the default IBEAM otherwise
  158. if (cast(HWND)wParam == hwnd)
  159. {
  160. POINT pt;
  161. GetCursorPos(&pt);
  162. ScreenToClient(hwndEdit, &pt);
  163. if (MouseInSelection(hwndEdit, MAKELPARAM(pt.x, pt.y)))
  164. {
  165. SetCursor(LoadCursor(null, MAKEINTRESOURCE(IDC_ARROW)));
  166. }
  167. else
  168. {
  169. SetCursor(LoadCursor(null, MAKEINTRESOURCE(IDC_IBEAM)));
  170. }
  171. }
  172. return TRUE;
  173. case WM_MOUSEMOVE:
  174. // if the mouse is held down then start a drag-drop
  175. if (fMouseDown)
  176. {
  177. IDataObject pDataObject;
  178. IDropSource pDropSource;
  179. DWORD dwEffect;
  180. DWORD dwResult;
  181. FORMATETC fmtetc = { CF_TEXT, null, DVASPECT.DVASPECT_CONTENT, -1, TYMED.TYMED_HGLOBAL };
  182. STGMEDIUM stgmed = { TYMED.TYMED_HGLOBAL };
  183. // transfer the current selection into the IDataObject
  184. stgmed.hGlobal = CopySelection(hwndEdit);
  185. // Create IDataObject and IDropSource COM objects
  186. pDropSource = newCom!CDropSource();
  187. scope(exit) pDropSource.Release();
  188. pDataObject = newCom!DataObject(FormatStore(fmtetc, stgmed));
  189. scope(exit) pDataObject.Release();
  190. // Star the drag & drop operation
  191. dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT.DROPEFFECT_COPY | DROPEFFECT.DROPEFFECT_MOVE, &dwEffect);
  192. // success!
  193. if (dwResult == DRAGDROP_S_DROP)
  194. {
  195. if (dwEffect & DROPEFFECT.DROPEFFECT_MOVE)
  196. {
  197. MessageBox(null, "Moving", "Info", MB_OK);
  198. // todo: remove selection from edit control
  199. }
  200. }
  201. else if (dwResult == DRAGDROP_S_CANCEL) // cancelled
  202. {
  203. }
  204. ReleaseCapture();
  205. fMouseDown = FALSE;
  206. fDidDragDrop = TRUE;
  207. }
  208. break;
  209. case WM_LBUTTONUP:
  210. // stop drag-drop from happening when the mouse is released.
  211. if (fMouseDown)
  212. {
  213. ReleaseCapture();
  214. fMouseDown = FALSE;
  215. if (fDidDragDrop == FALSE)
  216. ClearSelection(hwnd);
  217. }
  218. break;
  219. default:
  220. }
  221. return CallWindowProc(OldEditWndProc, hwnd, msg, wParam, lParam);
  222. }
  223. // Is the mouse cursor within the edit control's selected text?
  224. //
  225. // Return TRUE/FALSE
  226. //
  227. BOOL MouseInSelection(HWND hwndEdit, LPARAM MouseMsgParam)
  228. {
  229. DWORD nSelStart;
  230. DWORD nSelEnd;
  231. // get the selection inside the edit control
  232. SendMessage(hwndEdit, EM_GETSEL, cast(WPARAM)&nSelStart, cast(LPARAM)&nSelEnd);
  233. if (nSelStart != nSelEnd)
  234. {
  235. DWORD nCurPos;
  236. // Get the cursor position the mouse has clicked on
  237. nCurPos = SendMessage(hwndEdit, EM_CHARFROMPOS, 0, MouseMsgParam);
  238. nCurPos = LOWORD(nCurPos);
  239. // Did the mouse click inside the active selection?
  240. return (nCurPos >= nSelStart && nCurPos < nSelEnd) ? TRUE : FALSE;
  241. }
  242. return FALSE;
  243. }
  244. // Remove any selection from the edit control
  245. void ClearSelection(HWND hwndEdit)
  246. {
  247. SendMessage(hwndEdit, EM_SETSEL, -1, -1);
  248. }
  249. // Copy selected text to an HGLOBAL and return it
  250. HGLOBAL CopySelection(HWND hwndEdit)
  251. {
  252. DWORD nSelStart, nSelEnd;
  253. DWORD nSelLength, nEditLength;
  254. HGLOBAL hMem;
  255. char* ptr;
  256. char* tmp;
  257. SendMessage(hwndEdit, EM_GETSEL, cast(WPARAM)&nSelStart, cast(LPARAM)&nSelEnd);
  258. nSelLength = nSelEnd - nSelStart;
  259. // get the entire contents of the control
  260. nEditLength = SendMessage(hwndEdit, EM_GETLIMITTEXT, 0, 0);
  261. tmp = cast(char*)malloc(nEditLength);
  262. SendMessage(hwndEdit, WM_GETTEXT, nEditLength, cast(LPARAM)tmp);
  263. hMem = GlobalAlloc(GHND, nSelLength + 1);
  264. ptr = cast(char*)GlobalLock(hMem);
  265. // copy the selected text and null-terminate
  266. memcpy(ptr, tmp + nSelStart, nSelLength);
  267. ptr[nSelLength] = '\0';
  268. GlobalUnlock(hMem);
  269. free(tmp);
  270. return hMem;
  271. }