Mercurial > projects > dwt-win
annotate dwt/ole/win32/OleClientSite.d @ 212:ab60f3309436
reverted the char[] to String and use the an alias.
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 05 May 2008 00:12:38 +0200 |
parents | 619faee45ef6 |
children | fd9c62a2998e |
rev | line source |
---|---|
97 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2007 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
98 | 10 * Port to the D programming language: |
11 * Frank Benoit <benoit@tionex.de> | |
97 | 12 *******************************************************************************/ |
13 module dwt.ole.win32.OleClientSite; | |
14 | |
15 import dwt.dwthelper.File; | |
16 import dwt.dwthelper.FileInputStream; | |
17 import dwt.dwthelper.FileOutputStream; | |
18 import dwt.dwthelper.utils; | |
19 | |
20 import dwt.DWT; | |
21 import dwt.DWTException; | |
22 import dwt.graphics.Point; | |
23 import dwt.graphics.Rectangle; | |
24 import dwt.internal.Compatibility; | |
25 // import dwt.internal.ole.win32.CAUUID; | |
26 // import dwt.internal.ole.win32.COM; | |
27 // import dwt.internal.ole.win32.COMObject; | |
28 // import dwt.internal.ole.win32.GUID; | |
29 // import dwt.internal.ole.win32.IDispatch; | |
30 // import dwt.internal.ole.win32.IMoniker; | |
31 // import dwt.internal.ole.win32.IOleCommandTarget; | |
32 // import dwt.internal.ole.win32.IOleDocument; | |
33 // import dwt.internal.ole.win32.IOleDocumentView; | |
34 // import dwt.internal.ole.win32.IOleInPlaceObject; | |
35 // import dwt.internal.ole.win32.IOleLink; | |
36 // import dwt.internal.ole.win32.IOleObject; | |
37 // import dwt.internal.ole.win32.IPersist; | |
38 // import dwt.internal.ole.win32.IPersistStorage; | |
39 // import dwt.internal.ole.win32.ISpecifyPropertyPages; | |
40 // import dwt.internal.ole.win32.IStorage; | |
41 // import dwt.internal.ole.win32.IStream; | |
42 // import dwt.internal.ole.win32.IUnknown; | |
43 // import dwt.internal.ole.win32.IViewObject2; | |
44 // import dwt.internal.ole.win32.OLECMD; | |
45 // import dwt.internal.ole.win32.OLEINPLACEFRAMEINFO; | |
46 import dwt.internal.win32.OS; | |
98 | 47 import dwt.internal.ole.win32.extras; |
48 import dwt.internal.ole.win32.OAIDL; | |
49 import dwt.internal.ole.win32.OLEIDL; | |
50 import dwt.internal.ole.win32.OBJIDL; | |
51 import dwt.internal.ole.win32.DOCOBJ; | |
52 import dwt.internal.ole.win32.COM; | |
53 import dwt.internal.ole.win32.ifs; | |
97 | 54 |
55 import dwt.widgets.Composite; | |
56 import dwt.widgets.Event; | |
57 import dwt.widgets.Listener; | |
58 import dwt.widgets.Menu; | |
59 import dwt.widgets.Shell; | |
60 | |
98 | 61 import dwt.ole.win32.OleFrame; |
62 import dwt.ole.win32.Variant; | |
63 import dwt.ole.win32.OLE; | |
64 | |
97 | 65 |
66 /** | |
67 * OleClientSite provides a site to manage an embedded OLE Document within a container. | |
68 * | |
69 * <p>The OleClientSite provides the following capabilities: | |
70 * <ul> | |
71 * <li>creates the in-place editor for a blank document or opening an existing OLE Document | |
72 * <li>lays the editor out | |
73 * <li>provides a mechanism for activating and deactivating the Document | |
74 * <li>provides a mechanism for saving changes made to the document | |
75 * </ul> | |
76 * | |
77 * <p>This object implements the OLE Interfaces IUnknown, IOleClientSite, IAdviseSink, | |
78 * IOleInPlaceSite | |
79 * | |
80 * <p>Note that although this class is a subclass of <code>Composite</code>, | |
81 * it does not make sense to add <code>Control</code> children to it, | |
82 * or set a layout on it. | |
83 * </p><p> | |
84 * <dl> | |
85 * <dt><b>Styles</b> <dd>BORDER | |
86 * <dt><b>Events</b> <dd>Dispose, Move, Resize | |
87 * </dl> | |
88 * | |
89 */ | |
90 public class OleClientSite : Composite { | |
91 | |
92 // Interfaces for this Ole Client Container | |
98 | 93 private _IUnknownImpl iUnknown; |
94 private _IOleClientSiteImpl iOleClientSite; | |
95 private _IAdviseSinkImpl iAdviseSink; | |
96 private _IOleInPlaceSiteImpl iOleInPlaceSite; | |
97 private _IOleDocumentSiteImpl iOleDocumentSite; | |
97 | 98 |
98 | 99 protected GUID* appClsid; |
100 private GUID* objClsid; | |
97 | 101 private int refCount; |
102 | |
103 // References to the associated Frame. | |
98 | 104 package OleFrame frame; |
97 | 105 |
106 // Access to the embedded/linked Ole Object | |
98 | 107 protected IUnknown objIUnknown; |
108 protected IOleObject objIOleObject; | |
109 protected IViewObject2 objIViewObject2; | |
97 | 110 protected IOleInPlaceObject objIOleInPlaceObject; |
98 | 111 protected IOleCommandTarget objIOleCommandTarget; |
112 protected IOleDocumentView objDocumentView; | |
97 | 113 |
114 // Related storage information | |
115 protected IStorage tempStorage; // IStorage interface of the receiver | |
116 | |
117 // Internal state and style information | |
118 private int aspect; // the display aspect of the embedded object, e.g., DvaspectContent or DvaspectIcon | |
119 private int type; // Indicates the type of client that can be supported inside this container | |
120 private bool isStatic; // Indicates item's display is static, i.e., a bitmap, metafile, etc. | |
121 | |
98 | 122 private RECT borderWidths; |
123 private RECT indent; | |
97 | 124 private bool inUpdate = false; |
125 private bool inInit = true; | |
126 private bool inDispose = false; | |
127 | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
128 private static const String WORDPROGID = "Word.Document"; //$NON-NLS-1$ |
97 | 129 |
130 private Listener listener; | |
131 | |
98 | 132 enum{ |
133 STATE_NONE = 0, | |
134 STATE_RUNNING = 1, | |
135 STATE_INPLACEACTIVE = 2, | |
136 STATE_UIACTIVE = 3, | |
137 STATE_ACTIVE = 4, | |
138 } | |
97 | 139 int state = STATE_NONE; |
140 | |
98 | 141 protected this(Composite parent, int style) { |
97 | 142 /* |
143 * NOTE: this constructor should never be used by itself because it does | |
144 * not create an Ole Object | |
145 */ | |
146 super(parent, style); | |
147 | |
148 createCOMInterfaces(); | |
149 | |
150 // install the Ole Frame for this Client Site | |
151 while (parent !is null) { | |
98 | 152 if ( auto frame = cast(OleFrame)parent){ |
153 frame = frame; | |
97 | 154 break; |
155 } | |
156 parent = parent.getParent(); | |
157 } | |
98 | 158 if (frame is null) OLE.error (__FILE__, __LINE__, DWT.ERROR_INVALID_ARGUMENT); |
97 | 159 frame.AddRef(); |
160 | |
161 aspect = COM.DVASPECT_CONTENT; | |
162 type = COM.OLEEMBEDDED; | |
163 isStatic = false; | |
164 | |
98 | 165 listener = new class() Listener { |
97 | 166 public void handleEvent(Event e) { |
167 switch (e.type) { | |
168 case DWT.Resize : | |
169 case DWT.Move : onResize(e); break; | |
170 case DWT.Dispose : onDispose(e); break; | |
171 case DWT.FocusIn: onFocusIn(e); break; | |
172 case DWT.FocusOut: onFocusOut(e); break; | |
173 case DWT.Paint: onPaint(e); break; | |
174 case DWT.Traverse: onTraverse(e); break; | |
175 case DWT.KeyDown: /* required for traversal */ break; | |
176 default : | |
98 | 177 OLE.error (__FILE__, __LINE__, DWT.ERROR_NOT_IMPLEMENTED); |
97 | 178 } |
179 } | |
180 }; | |
181 | |
182 frame.addListener(DWT.Resize, listener); | |
183 frame.addListener(DWT.Move, listener); | |
184 addListener(DWT.Dispose, listener); | |
185 addListener(DWT.FocusIn, listener); | |
186 addListener(DWT.FocusOut, listener); | |
187 addListener(DWT.Paint, listener); | |
188 addListener(DWT.Traverse, listener); | |
189 addListener(DWT.KeyDown, listener); | |
190 } | |
191 /** | |
192 * Create an OleClientSite child widget using the OLE Document type associated with the | |
193 * specified file. The OLE Document type is determined either through header information in the file | |
194 * or through a Registry entry for the file extension. Use style bits to select a particular look | |
195 * or set of properties. | |
196 * | |
197 * @param parent a composite widget; must be an OleFrame | |
198 * @param style the bitwise OR'ing of widget styles | |
199 * @param file the file that is to be opened in this OLE Document | |
200 * | |
201 * @exception IllegalArgumentException | |
202 * <ul><li>ERROR_NULL_ARGUMENT when the parent is null | |
203 * <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul> | |
204 * @exception DWTException | |
205 * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread | |
206 * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object | |
207 * <li>ERROR_CANNOT_OPEN_FILE when failed to open file | |
208 * <li>ERROR_INTERFACE_NOT_FOUND when unable to create callbacks for OLE Interfaces | |
209 * <li>ERROR_INVALID_CLASSID | |
210 * </ul> | |
211 */ | |
98 | 212 public this(Composite parent, int style, File file) { |
97 | 213 this(parent, style); |
214 try { | |
215 | |
216 if (file is null || file.isDirectory() || !file.exists()) | |
98 | 217 OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_ARGUMENT); |
97 | 218 |
219 // Is there an associated CLSID? | |
220 appClsid = new GUID(); | |
98 | 221 TCHAR* fileName = StrToTCHARz( 0, file.getAbsolutePath() ); |
97 | 222 int result = COM.GetClassFile(fileName, appClsid); |
223 if (result !is COM.S_OK) | |
98 | 224 OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID, result); |
97 | 225 // associated CLSID may not be installed on this machine |
226 if (getProgramID() is null) | |
98 | 227 OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID, result); |
97 | 228 |
229 // Open a temporary storage object | |
230 tempStorage = createTempStorage(); | |
231 | |
232 // Create ole object with storage object | |
98 | 233 result = COM.OleCreateFromFile(appClsid, fileName, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown); |
97 | 234 if (result !is COM.S_OK) |
98 | 235 OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result); |
97 | 236 |
237 // Init sinks | |
238 addObjectReferences(); | |
239 | |
98 | 240 if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING; |
97 | 241 } catch (DWTException e) { |
242 dispose(); | |
243 disposeCOMInterfaces(); | |
244 throw e; | |
245 } | |
246 } | |
247 /** | |
248 * Create an OleClientSite child widget to edit a blank document using the specified OLE Document | |
249 * application. Use style bits to select a particular look or set of properties. | |
250 * | |
251 * @param parent a composite widget; must be an OleFrame | |
252 * @param style the bitwise OR'ing of widget styles | |
253 * @param progId the unique program identifier of am OLE Document application; | |
254 * the value of the ProgID key or the value of the VersionIndependentProgID key specified | |
255 * in the registry for the desired OLE Document (for example, the VersionIndependentProgID | |
256 * for Word is Word.Document) | |
257 * | |
258 * @exception IllegalArgumentException | |
259 *<ul> | |
260 * <li>ERROR_NULL_ARGUMENT when the parent is null | |
261 * <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame | |
262 *</ul> | |
263 * @exception DWTException | |
264 * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread | |
265 * <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID | |
266 * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object | |
267 * </ul> | |
268 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
269 public this(Composite parent, int style, String progId) { |
97 | 270 this(parent, style); |
271 try { | |
272 appClsid = getClassID(progId); | |
273 if (appClsid is null) | |
98 | 274 OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID); |
97 | 275 |
276 // Open a temporary storage object | |
277 tempStorage = createTempStorage(); | |
278 | |
279 // Create ole object with storage object | |
98 | 280 HRESULT result = COM.OleCreate(appClsid, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown); |
97 | 281 if (result !is COM.S_OK) |
98 | 282 OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result); |
97 | 283 |
284 // Init sinks | |
285 addObjectReferences(); | |
286 | |
98 | 287 if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING; |
97 | 288 |
289 } catch (DWTException e) { | |
290 dispose(); | |
291 disposeCOMInterfaces(); | |
292 throw e; | |
293 } | |
294 } | |
295 /** | |
296 * Create an OleClientSite child widget to edit the specified file using the specified OLE Document | |
297 * application. Use style bits to select a particular look or set of properties. | |
298 * <p> | |
299 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
300 * API for <code>OleClientSite</code>. It is marked public only so that it | |
301 * can be shared within the packages provided by DWT. It is not | |
302 * available on all platforms, and should never be called from | |
303 * application code. | |
304 * </p> | |
305 * @param parent a composite widget; must be an OleFrame | |
306 * @param style the bitwise OR'ing of widget styles | |
307 * @param progId the unique program identifier of am OLE Document application; | |
308 * the value of the ProgID key or the value of the VersionIndependentProgID key specified | |
309 * in the registry for the desired OLE Document (for example, the VersionIndependentProgID | |
310 * for Word is Word.Document) | |
311 * @param file the file that is to be opened in this OLE Document | |
312 * | |
313 * @exception IllegalArgumentException | |
314 * <ul><li>ERROR_NULL_ARGUMENT when the parent is null | |
315 * <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul> | |
316 * @exception DWTException | |
317 * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread | |
318 * <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID | |
319 * <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object | |
320 * <li>ERROR_CANNOT_OPEN_FILE when failed to open file | |
321 * </ul> | |
322 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
323 public this(Composite parent, int style, String progId, File file) { |
97 | 324 this(parent, style); |
325 try { | |
98 | 326 if (file is null || file.isDirectory() || !file.exists()) OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_ARGUMENT); |
97 | 327 appClsid = getClassID(progId); |
98 | 328 if (appClsid is null) OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID); |
97 | 329 |
330 // Are we opening this file with the preferred OLE object? | |
98 | 331 wchar* fileName = StrToWCHARz(file.getAbsolutePath()); |
332 GUID* fileClsid = new GUID(); | |
97 | 333 COM.GetClassFile(fileName, fileClsid); |
334 | |
335 if (COM.IsEqualGUID(appClsid, fileClsid)){ | |
336 // Using the same application that created file, therefore, use default mechanism. | |
337 tempStorage = createTempStorage(); | |
338 // Create ole object with storage object | |
98 | 339 HRESULT result = COM.OleCreateFromFile(appClsid, fileName, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown); |
340 if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result); | |
97 | 341 } else { |
342 // Not using the same application that created file, therefore, copy from original file to a new storage file | |
343 IStorage storage = null; | |
344 if (COM.StgIsStorageFile(fileName) is COM.S_OK) { | |
345 int mode = COM.STGM_READ | COM.STGM_TRANSACTED | COM.STGM_SHARE_EXCLUSIVE; | |
98 | 346 HRESULT result = COM.StgOpenStorage(fileName, null, mode, null, 0, &storage); //Does an AddRef if successful |
347 if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result); | |
97 | 348 } else { |
349 // Original file is not a Storage file so copy contents to a stream in a new storage file | |
350 int mode = COM.STGM_READWRITE | COM.STGM_DIRECT | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE; | |
98 | 351 HRESULT result = COM.StgCreateDocfile(null, mode | COM.STGM_DELETEONRELEASE, 0, &storage); // Increments ref count if successful |
352 if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result); | |
97 | 353 // Create a stream on the storage object. |
354 // Word does not follow the standard and does not use "CONTENTS" as the name of | |
355 // its primary stream | |
98 | 356 wchar* streamName = StrToWCHARz("CONTENTS"); //$NON-NLS-1$ |
357 GUID* wordGUID = getClassID(WORDPROGID); | |
97 | 358 if (wordGUID !is null && COM.IsEqualGUID(appClsid, wordGUID)) streamName = "WordDocument"; //$NON-NLS-1$ |
98 | 359 IStream stream; |
360 result = storage.CreateStream(streamName, mode, 0, 0, &stream); // Increments ref count if successful | |
97 | 361 if (result !is COM.S_OK) { |
362 storage.Release(); | |
98 | 363 OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result); |
97 | 364 } |
365 try { | |
366 // Copy over data in file to named stream | |
367 FileInputStream fileInput = new FileInputStream(file); | |
368 int increment = 1024*4; | |
369 byte[] buffer = new byte[increment]; | |
370 int count = 0; | |
371 while((count = fileInput.read(buffer)) > 0){ | |
98 | 372 auto pv = COM.CoTaskMemAlloc(count); |
373 OS.MoveMemory(pv, buffer.ptr, count); | |
97 | 374 result = stream.Write(pv, count, null) ; |
375 COM.CoTaskMemFree(pv); | |
376 if (result !is COM.S_OK) { | |
377 fileInput.close(); | |
378 stream.Release(); | |
379 storage.Release(); | |
98 | 380 OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result); |
97 | 381 } |
382 } | |
383 fileInput.close(); | |
384 stream.Commit(COM.STGC_DEFAULT); | |
385 stream.Release(); | |
386 } catch (IOException err) { | |
387 stream.Release(); | |
388 storage.Release(); | |
98 | 389 OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE); |
97 | 390 } |
391 } | |
392 | |
393 // Open a temporary storage object | |
394 tempStorage = createTempStorage(); | |
395 // Copy over contents of file | |
98 | 396 HRESULT result = storage.CopyTo(0, null, null, tempStorage); |
97 | 397 storage.Release(); |
98 | 398 if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result); |
97 | 399 |
400 // create ole client | |
98 | 401 result = COM.CoCreateInstance(appClsid, null, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, &COM.IIDIUnknown, cast(void**)&objIUnknown); |
402 if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result); | |
97 | 403 // get the persistent storage of the ole client |
98 | 404 IPersistStorage iPersistStorage; |
405 result = objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&iPersistStorage); | |
406 if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result); | |
97 | 407 // load the contents of the file into the ole client site |
98 | 408 result = iPersistStorage.Load(tempStorage); |
97 | 409 iPersistStorage.Release(); |
98 | 410 if (result !is COM.S_OK)OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result); |
97 | 411 } |
412 | |
413 // Init sinks | |
414 addObjectReferences(); | |
415 | |
98 | 416 if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING; |
97 | 417 |
418 } catch (DWTException e) { | |
419 dispose(); | |
420 disposeCOMInterfaces(); | |
421 throw e; | |
422 } | |
423 } | |
424 protected void addObjectReferences() { | |
425 // | |
98 | 426 IPersist objIPersist; |
427 if (objIUnknown.QueryInterface(&COM.IIDIPersist, cast(void**)&objIPersist) is COM.S_OK) { | |
428 GUID* tempid = new GUID(); | |
97 | 429 if (objIPersist.GetClassID(tempid) is COM.S_OK) |
430 objClsid = tempid; | |
431 objIPersist.Release(); | |
432 } | |
433 | |
434 // | |
98 | 435 HRESULT result = objIUnknown.QueryInterface(&COM.IIDIViewObject2, cast(void**)&objIViewObject2); |
97 | 436 if (result !is COM.S_OK) |
98 | 437 OLE.error (__FILE__, __LINE__, OLE.ERROR_INTERFACE_NOT_FOUND, result); |
438 objIViewObject2.SetAdvise(aspect, 0, iAdviseSink); | |
97 | 439 |
440 // | |
98 | 441 result = objIUnknown.QueryInterface(&COM.IIDIOleObject, cast(void**)&objIOleObject); |
97 | 442 if (result !is COM.S_OK) |
98 | 443 OLE.error (__FILE__, __LINE__, OLE.ERROR_INTERFACE_NOT_FOUND, result); |
444 objIOleObject.SetClientSite(iOleClientSite); | |
445 uint pdwConnection; | |
446 objIOleObject.Advise(iAdviseSink, &pdwConnection); | |
97 | 447 objIOleObject.SetHostNames("main", "main"); //$NON-NLS-1$ //$NON-NLS-2$ |
448 | |
449 // Notify the control object that it is embedded in an OLE container | |
98 | 450 COM.OleSetContainedObject(objIUnknown, true); |
97 | 451 |
452 // Is OLE object linked or embedded? | |
98 | 453 IOleLink objIOleLink; |
454 if (objIUnknown.QueryInterface(&COM.IIDIOleLink, cast(void**)&objIOleLink) is COM.S_OK) { | |
455 IMoniker objIMoniker; | |
456 if (objIOleLink.GetSourceMoniker(&objIMoniker) is COM.S_OK) { | |
97 | 457 objIMoniker.Release(); |
458 type = COM.OLELINKED; | |
459 objIOleLink.BindIfRunning(); | |
460 } else { | |
461 isStatic = true; | |
462 } | |
463 objIOleLink.Release(); | |
464 } | |
465 } | |
466 protected int AddRef() { | |
467 refCount++; | |
468 return refCount; | |
469 } | |
470 private int CanInPlaceActivate() { | |
471 if (aspect is COM.DVASPECT_CONTENT && type is COM.OLEEMBEDDED) | |
472 return COM.S_OK; | |
473 | |
474 return COM.S_FALSE; | |
475 } | |
476 private int ContextSensitiveHelp(int fEnterMode) { | |
477 return COM.S_OK; | |
478 } | |
479 protected void createCOMInterfaces() { | |
98 | 480 iUnknown = new _IUnknownImpl(this); |
481 iOleClientSite = new _IOleClientSiteImpl(this); | |
482 iAdviseSink = new _IAdviseSinkImpl(this); | |
483 iOleInPlaceSite = new _IOleInPlaceSiteImpl(this); | |
484 iOleDocumentSite = new _IOleDocumentSiteImpl(this); | |
97 | 485 } |
486 protected IStorage createTempStorage() { | |
98 | 487 IStorage tmpStorage; |
97 | 488 int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_DELETEONRELEASE; |
98 | 489 HRESULT result = COM.StgCreateDocfile(null, grfMode, 0, &tmpStorage); |
490 if (result !is COM.S_OK) OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_FILE, result); | |
491 return (tmpStorage); | |
97 | 492 } |
493 /** | |
494 * Deactivates an active in-place object and discards the object's undo state. | |
495 */ | |
496 public void deactivateInPlaceClient() { | |
497 if (objIOleInPlaceObject !is null) { | |
498 objIOleInPlaceObject.InPlaceDeactivate(); | |
499 } | |
500 } | |
501 private void deleteTempStorage() { | |
502 //Destroy this item's contents in the temp root IStorage. | |
503 if (tempStorage !is null){ | |
504 tempStorage.Release(); | |
505 } | |
506 tempStorage = null; | |
507 } | |
508 protected void disposeCOMInterfaces() { | |
509 iUnknown = null; | |
510 iOleClientSite = null; | |
511 iAdviseSink = null; | |
512 iOleInPlaceSite = null; | |
513 iOleDocumentSite = null; | |
514 } | |
515 /** | |
516 * Requests that the OLE Document or ActiveX Control perform an action; actions are almost always | |
517 * changes to the activation state. | |
518 * | |
519 * @param verb the operation that is requested. This is one of the OLE.OLEIVERB_ values | |
520 * | |
521 * @return an HRESULT value indicating the success of the operation request; OLE.S_OK indicates | |
522 * success | |
523 */ | |
524 public int doVerb(int verb) { | |
525 // Not all OLE clients (for example PowerPoint) can be set into the running state in the constructor. | |
526 // The fix is to ensure that the client is in the running state before invoking any verb on it. | |
527 if (state is STATE_NONE) { | |
98 | 528 if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING; |
97 | 529 } |
530 if (state is STATE_NONE || isStatic) | |
531 return COM.E_FAIL; | |
532 | |
533 // See PR: 1FV9RZW | |
98 | 534 RECT rect; |
535 OS.GetClientRect(handle, &rect); | |
536 int result = objIOleObject.DoVerb(verb, null, iOleClientSite, 0, handle, &rect); | |
97 | 537 |
538 if (state !is STATE_RUNNING && inInit) { | |
539 updateStorage(); | |
540 inInit = false; | |
541 } | |
542 return result; | |
543 } | |
544 /** | |
545 * Asks the OLE Document or ActiveX Control to execute a command from a standard | |
546 * list of commands. The OLE Document or ActiveX Control must support the IOleCommandTarget | |
547 * interface. The OLE Document or ActiveX Control does not have to support all the commands | |
548 * in the standard list. To check if a command is supported, you can call queryStatus with | |
549 * the cmdID. | |
550 * | |
551 * @param cmdID the ID of a command; these are the OLE.OLECMDID_ values - a small set of common | |
552 * commands | |
553 * @param options the optional flags; these are the OLE.OLECMDEXECOPT_ values | |
554 * @param in the argument for the command | |
555 * @param out the return value of the command | |
556 * | |
557 * @return an HRESULT value; OLE.S_OK is returned if successful | |
558 * | |
559 */ | |
98 | 560 public int exec(int cmdID, int options, Variant pvaIn, Variant pvaOut) { |
97 | 561 |
562 if (objIOleCommandTarget is null) { | |
98 | 563 if (objIUnknown.QueryInterface(&COM.IIDIOleCommandTarget, cast(void**)&objIOleCommandTarget) !is COM.S_OK) |
97 | 564 return OLE.ERROR_INTERFACE_NOT_FOUND; |
565 } | |
566 | |
98 | 567 VARIANT* pIn = null; |
568 VARIANT* pOut = null; | |
569 | |
570 if(pvaIn){ | |
571 pIn = new VARIANT(); | |
572 pvaIn.getData(pIn); | |
97 | 573 } |
98 | 574 if(pvaOut){ |
575 pOut = new VARIANT(); | |
576 pvaOut.getData(pOut); | |
97 | 577 } |
578 | |
98 | 579 HRESULT result = objIOleCommandTarget.Exec(null, cmdID, options, pIn, pOut); |
97 | 580 |
98 | 581 if(pIn) { |
582 COM.VariantClear(pIn); | |
97 | 583 } |
98 | 584 |
585 if(pOut) { | |
586 pvaOut.setData(pOut); | |
587 COM.VariantClear(pOut); | |
97 | 588 } |
589 | |
590 return result; | |
591 } | |
592 IDispatch getAutomationObject() { | |
98 | 593 IDispatch ppvObject; |
594 if (objIUnknown.QueryInterface(&COM.IIDIDispatch, cast(void**)&ppvObject) !is COM.S_OK) | |
97 | 595 return null; |
98 | 596 return ppvObject; |
97 | 597 } |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
598 protected GUID* getClassID(String clientName) { |
97 | 599 // create a GUID struct to hold the result |
98 | 600 GUID* guid = new GUID(); |
97 | 601 |
602 // create a null terminated array of char | |
98 | 603 wchar* buffer = null; |
97 | 604 if (clientName !is null) { |
98 | 605 buffer = StrToWCHARz(clientName);; |
97 | 606 } |
607 if (COM.CLSIDFromProgID(buffer, guid) !is COM.S_OK){ | |
98 | 608 HRESULT result = COM.CLSIDFromString(buffer, guid); |
97 | 609 if (result !is COM.S_OK) return null; |
610 } | |
611 return guid; | |
612 } | |
98 | 613 |
614 private HRESULT GetContainer(IOleContainer* ppContainer) { | |
97 | 615 /* Simple containers that do not support links to their embedded |
616 * objects probably do not need to implement this method. Instead, | |
617 * they can return E_NOINTERFACE and set ppContainer to NULL. | |
618 */ | |
98 | 619 if (ppContainer !is null) |
620 *ppContainer = null; | |
97 | 621 return COM.E_NOINTERFACE; |
622 } | |
98 | 623 |
624 private SIZE* getExtent() { | |
625 SIZE* sizel = new SIZE(); | |
97 | 626 // get the current size of the embedded OLENatives object |
627 if (objIOleObject !is null) { | |
98 | 628 if ( objIViewObject2 !is null && !COM.OleIsRunning(objIOleObject)) { |
97 | 629 objIViewObject2.GetExtent(aspect, -1, null, sizel); |
630 } else { | |
631 objIOleObject.GetExtent(aspect, sizel); | |
632 } | |
633 } | |
634 return xFormHimetricToPixels(sizel); | |
635 } | |
636 public Rectangle getIndent() { | |
637 return new Rectangle(indent.left, indent.right, indent.top, indent.bottom); | |
638 } | |
639 /** | |
640 * Returns the program ID of the OLE Document or ActiveX Control. | |
641 * | |
642 * @return the program ID of the OLE Document or ActiveX Control | |
643 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
644 public String getProgramID(){ |
97 | 645 if (appClsid !is null){ |
98 | 646 wchar* hMem; |
647 if (COM.ProgIDFromCLSID(appClsid, &hMem) is COM.S_OK) { | |
97 | 648 int length = OS.GlobalSize(hMem); |
98 | 649 auto ptr = OS.GlobalLock(hMem); |
650 wchar[] buffer = new wchar[length]; | |
651 COM.MoveMemory(buffer.ptr, ptr, length); | |
97 | 652 OS.GlobalUnlock(hMem); |
653 OS.GlobalFree(hMem); | |
654 | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
655 String result = WCHARzToStr(buffer.ptr); |
97 | 656 // remove null terminator |
98 | 657 //int index = result.indexOf("\0"); |
658 return result;//.substring(0, index); | |
97 | 659 } |
660 } | |
661 return null; | |
662 } | |
98 | 663 int ActivateMe(IOleDocumentView pViewToActivate) { |
664 if (pViewToActivate is null) { | |
665 void* ppvObject; | |
666 if (objIUnknown.QueryInterface(&COM.IIDIOleDocument, &ppvObject) !is COM.S_OK) return COM.E_FAIL; | |
667 IOleDocument objOleDocument = cast(IOleDocument)ppvObject; | |
668 if (objOleDocument.CreateView(iOleInPlaceSite, null, 0, &objDocumentView) !is COM.S_OK) return COM.E_FAIL; | |
97 | 669 objOleDocument.Release(); |
670 } else { | |
98 | 671 objDocumentView = pViewToActivate; |
97 | 672 objDocumentView.AddRef(); |
98 | 673 objDocumentView.SetInPlaceSite(iOleInPlaceSite); |
97 | 674 } |
675 objDocumentView.UIActivate(1);//TRUE | |
98 | 676 RECT* rect = getRect(); |
97 | 677 objDocumentView.SetRect(rect); |
678 objDocumentView.Show(1);//TRUE | |
679 return COM.S_OK; | |
680 } | |
98 | 681 protected int GetWindow(HWND* phwnd) { |
682 if (phwnd is null) | |
97 | 683 return COM.E_INVALIDARG; |
684 if (frame is null) { | |
98 | 685 *phwnd = null; |
97 | 686 return COM.E_NOTIMPL; |
687 } | |
688 | |
689 // Copy the Window's handle into the memory passed in | |
98 | 690 *phwnd = frame.handle; |
97 | 691 return COM.S_OK; |
692 } | |
98 | 693 RECT* getRect() { |
97 | 694 Point location = this.getLocation(); |
695 Rectangle area = frame.getClientArea(); | |
98 | 696 RECT* rect = new RECT(); |
97 | 697 rect.left = location.x; |
698 rect.top = location.y; | |
699 rect.right = location.x + area.width - borderWidths.left - borderWidths.right; | |
700 rect.bottom = location.y + area.height - borderWidths.top - borderWidths.bottom; | |
701 return rect; | |
702 } | |
98 | 703 |
704 private int GetWindowContext(IOleInPlaceFrame* ppFrame, IOleInPlaceUIWindow* ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) { | |
705 if (frame is null || ppFrame is null) | |
97 | 706 return COM.E_NOTIMPL; |
707 | |
708 // fill in frame handle | |
98 | 709 auto iOleInPlaceFrame = frame.getIOleInPlaceFrame(); |
710 *ppFrame = iOleInPlaceFrame; | |
97 | 711 frame.AddRef(); |
712 | |
713 // null out document handle | |
98 | 714 if (ppDoc !is null) *ppDoc = null; |
97 | 715 |
716 // fill in position and clipping info | |
98 | 717 RECT* rect = getRect(); |
718 if (lprcPosRect !is null) OS.MoveMemory(lprcPosRect, rect, RECT.sizeof); | |
719 if (lprcClipRect !is null) OS.MoveMemory(lprcClipRect, rect, RECT.sizeof); | |
97 | 720 |
721 // get frame info | |
98 | 722 OLEINPLACEFRAMEINFO* frameInfo = new OLEINPLACEFRAMEINFO(); |
97 | 723 frameInfo.cb = OLEINPLACEFRAMEINFO.sizeof; |
724 frameInfo.fMDIApp = 0; | |
725 frameInfo.hwndFrame = frame.handle; | |
726 Shell shell = getShell(); | |
727 Menu menubar = shell.getMenuBar(); | |
728 if (menubar !is null && !menubar.isDisposed()) { | |
98 | 729 auto hwnd = shell.handle; |
730 auto cAccel = OS.SendMessage(hwnd, OS.WM_APP, 0, 0); | |
97 | 731 if (cAccel !is 0) { |
98 | 732 auto hAccel = cast(HACCEL) OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0); |
733 if (hAccel !is null) { | |
97 | 734 frameInfo.cAccelEntries = cAccel; |
735 frameInfo.haccel = hAccel; | |
736 } | |
737 } | |
738 } | |
739 COM.MoveMemory(lpFrameInfo, frameInfo, OLEINPLACEFRAMEINFO.sizeof); | |
740 | |
741 return COM.S_OK; | |
742 } | |
743 public bool isDirty() { | |
744 /* | |
745 * Note: this method must return true unless it is absolutely clear that the | |
746 * contents of the Ole Document do not differ from the contents in the file | |
747 * on the file system. | |
748 */ | |
749 | |
750 // Get access to the persistent storage mechanism | |
98 | 751 IPersistStorage permStorage; |
752 if (objIOleObject.QueryInterface(&COM.IIDIPersistFile, cast(void**)&permStorage) !is COM.S_OK) | |
97 | 753 return true; |
754 // Are the contents of the permanent storage different from the file? | |
98 | 755 auto result = permStorage.IsDirty(); |
97 | 756 permStorage.Release(); |
757 if (result is COM.S_FALSE) return false; | |
758 return true; | |
759 } | |
760 public bool isFocusControl () { | |
761 checkWidget (); | |
98 | 762 auto focusHwnd = OS.GetFocus(); |
97 | 763 if (objIOleInPlaceObject is null) return (handle is focusHwnd); |
98 | 764 HWND phwnd; |
765 objIOleInPlaceObject.GetWindow(&phwnd); | |
766 while (focusHwnd !is null) { | |
767 if (phwnd is focusHwnd) return true; | |
97 | 768 focusHwnd = OS.GetParent(focusHwnd); |
769 } | |
770 return false; | |
771 } | |
772 private int OnClose() { | |
773 return COM.S_OK; | |
774 } | |
775 private int OnDataChange(int pFormatetc, int pStgmed) { | |
776 return COM.S_OK; | |
777 } | |
778 private void onDispose(Event e) { | |
779 inDispose = true; | |
780 if (state !is STATE_NONE) | |
781 doVerb(OLE.OLEIVERB_DISCARDUNDOSTATE); | |
782 deactivateInPlaceClient(); | |
783 releaseObjectInterfaces(); // Note, must release object interfaces before releasing frame | |
784 deleteTempStorage(); | |
785 | |
786 // remove listeners | |
787 removeListener(DWT.Dispose, listener); | |
788 removeListener(DWT.FocusIn, listener); | |
789 removeListener(DWT.Paint, listener); | |
790 removeListener(DWT.Traverse, listener); | |
791 removeListener(DWT.KeyDown, listener); | |
792 frame.removeListener(DWT.Resize, listener); | |
793 frame.removeListener(DWT.Move, listener); | |
794 | |
795 frame.Release(); | |
796 frame = null; | |
797 } | |
798 void onFocusIn(Event e) { | |
799 if (inDispose) return; | |
800 if (state !is STATE_UIACTIVE) doVerb(OLE.OLEIVERB_SHOW); | |
801 if (objIOleInPlaceObject is null) return; | |
802 if (isFocusControl()) return; | |
98 | 803 HWND phwnd; |
804 objIOleInPlaceObject.GetWindow(&phwnd); | |
805 if (phwnd is null) return; | |
806 OS.SetFocus(phwnd); | |
97 | 807 } |
808 void onFocusOut(Event e) { | |
809 } | |
810 private int OnInPlaceActivate() { | |
811 state = STATE_INPLACEACTIVE; | |
812 frame.setCurrentDocument(this); | |
813 if (objIOleObject is null) | |
814 return COM.S_OK; | |
815 int[] ppvObject = new int[1]; | |
98 | 816 if (objIOleObject.QueryInterface(&COM.IIDIOleInPlaceObject, cast(void**)&objIOleInPlaceObject) is COM.S_OK) { |
817 //objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]); | |
97 | 818 } |
819 return COM.S_OK; | |
820 } | |
821 private int OnInPlaceDeactivate() { | |
822 if (objIOleInPlaceObject !is null) objIOleInPlaceObject.Release(); | |
823 objIOleInPlaceObject = null; | |
824 state = STATE_RUNNING; | |
825 redraw(); | |
826 Shell shell = getShell(); | |
827 if (isFocusControl() || frame.isFocusControl()) { | |
828 shell.traverse(DWT.TRAVERSE_TAB_NEXT); | |
829 } | |
830 return COM.S_OK; | |
831 } | |
98 | 832 private int OnPosRectChange(LPRECT lprcPosRect) { |
97 | 833 Point size = getSize(); |
834 setExtent(size.x, size.y); | |
835 return COM.S_OK; | |
836 } | |
837 private void onPaint(Event e) { | |
838 if (state is STATE_RUNNING || state is STATE_INPLACEACTIVE) { | |
98 | 839 SIZE* size = getExtent(); |
97 | 840 Rectangle area = getClientArea(); |
98 | 841 RECT* rect = new RECT(); |
97 | 842 if (getProgramID().startsWith("Excel.Sheet")) { //$NON-NLS-1$ |
843 rect.left = area.x; rect.right = area.x + (area.height * size.cx / size.cy); | |
844 rect.top = area.y; rect.bottom = area.y + area.height; | |
845 } else { | |
846 rect.left = area.x; rect.right = area.x + size.cx; | |
847 rect.top = area.y; rect.bottom = area.y + size.cy; | |
848 } | |
849 | |
98 | 850 auto pArea = cast(RECT*)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, RECT.sizeof); |
97 | 851 OS.MoveMemory(pArea, rect, RECT.sizeof); |
98 | 852 COM.OleDraw(objIUnknown, aspect, e.gc.handle, pArea); |
97 | 853 OS.GlobalFree(pArea); |
854 } | |
855 } | |
856 private void onResize(Event e) { | |
857 Rectangle area = frame.getClientArea(); | |
858 setBounds(borderWidths.left, | |
859 borderWidths.top, | |
860 area.width - borderWidths.left - borderWidths.right, | |
861 area.height - borderWidths.top - borderWidths.bottom); | |
862 | |
863 setObjectRects(); | |
864 } | |
865 private void OnSave() { | |
866 } | |
867 private int OnShowWindow(int fShow) { | |
868 return COM.S_OK; | |
869 } | |
870 private int OnUIActivate() { | |
871 if (objIOleInPlaceObject is null) return COM.E_FAIL; | |
872 state = STATE_UIACTIVE; | |
98 | 873 HWND phwnd; |
874 if (objIOleInPlaceObject.GetWindow(&phwnd) is COM.S_OK) { | |
875 OS.SetWindowPos(phwnd, cast(HWND)OS.HWND_TOP, 0, 0, 0, 0, OS.SWP_NOSIZE | OS.SWP_NOMOVE); | |
97 | 876 } |
877 return COM.S_OK; | |
878 } | |
879 private int OnUIDeactivate(int fUndoable) { | |
880 // currently, we are ignoring the fUndoable flag | |
881 if (frame is null || frame.isDisposed()) return COM.S_OK; | |
882 state = STATE_INPLACEACTIVE; | |
98 | 883 frame.SetActiveObject(null, null); |
97 | 884 redraw(); |
885 Shell shell = getShell(); | |
886 if (isFocusControl() || frame.isFocusControl()) { | |
887 shell.traverse(DWT.TRAVERSE_TAB_NEXT); | |
888 } | |
889 Menu menubar = shell.getMenuBar(); | |
890 if (menubar is null || menubar.isDisposed()) | |
891 return COM.S_OK; | |
892 | |
98 | 893 auto shellHandle = shell.handle; |
97 | 894 OS.SetMenu(shellHandle, menubar.handle); |
98 | 895 return COM.OleSetMenuDescriptor(null, shellHandle, null, null, null); |
97 | 896 } |
897 private void onTraverse(Event event) { | |
898 switch (event.detail) { | |
899 case DWT.TRAVERSE_ESCAPE: | |
900 case DWT.TRAVERSE_RETURN: | |
901 case DWT.TRAVERSE_TAB_NEXT: | |
902 case DWT.TRAVERSE_TAB_PREVIOUS: | |
903 case DWT.TRAVERSE_PAGE_NEXT: | |
904 case DWT.TRAVERSE_PAGE_PREVIOUS: | |
905 case DWT.TRAVERSE_MNEMONIC: | |
906 event.doit = true; | |
907 break; | |
162
619faee45ef6
add missing default cases
Thomas Graber <d4rkdragon@gmail.com>
parents:
98
diff
changeset
|
908 default: |
97 | 909 } |
910 } | |
911 private int OnViewChange(int dwAspect, int lindex) { | |
912 return COM.S_OK; | |
913 } | |
98 | 914 protected int QueryInterface(REFIID riid, void ** ppvObject) { |
97 | 915 |
98 | 916 if (riid is null || ppvObject is null) |
97 | 917 return COM.E_NOINTERFACE; |
98 | 918 GUID* guid = new GUID(); |
97 | 919 COM.MoveMemory(guid, riid, GUID.sizeof); |
920 | |
98 | 921 if (COM.IsEqualGUID(guid, &COM.IIDIUnknown)) { |
922 *ppvObject = cast(void*)cast(IUnknown)iUnknown; | |
97 | 923 AddRef(); |
924 return COM.S_OK; | |
925 } | |
98 | 926 if (COM.IsEqualGUID(guid, &COM.IIDIAdviseSink)) { |
927 *ppvObject = cast(void*)cast(IAdviseSink)iAdviseSink; | |
97 | 928 AddRef(); |
929 return COM.S_OK; | |
930 } | |
98 | 931 if (COM.IsEqualGUID(guid, &COM.IIDIOleClientSite)) { |
932 *ppvObject = cast(void*)cast(IOleClientSite)iOleClientSite; | |
97 | 933 AddRef(); |
934 return COM.S_OK; | |
935 } | |
98 | 936 if (COM.IsEqualGUID(guid, &COM.IIDIOleInPlaceSite)) { |
937 *ppvObject = cast(void*)cast(IOleInPlaceSite)iOleInPlaceSite; | |
97 | 938 AddRef(); |
939 return COM.S_OK; | |
940 } | |
98 | 941 if (COM.IsEqualGUID(guid, &COM.IIDIOleDocumentSite )) { |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
942 String progID = getProgramID(); |
97 | 943 if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$ |
98 | 944 *ppvObject = cast(void*)cast(IOleDocumentSite)iOleDocumentSite; |
97 | 945 AddRef(); |
946 return COM.S_OK; | |
947 } | |
948 } | |
98 | 949 *ppvObject = null; |
97 | 950 return COM.E_NOINTERFACE; |
951 } | |
952 /** | |
953 * Returns the status of the specified command. The status is any bitwise OR'd combination of | |
954 * SWTOLE.OLECMDF_SUPPORTED, SWTOLE.OLECMDF_ENABLED, SWTOLE.OLECMDF_LATCHED, SWTOLE.OLECMDF_NINCHED. | |
955 * You can query the status of a command before invoking it with OleClientSite.exec. The | |
956 * OLE Document or ActiveX Control must support the IOleCommandTarget to make use of this method. | |
957 * | |
958 * @param cmd the ID of a command; these are the OLE.OLECMDID_ values - a small set of common | |
959 * commands | |
960 * | |
961 * @return the status of the specified command or 0 if unable to query the OLE Object; these are the | |
962 * OLE.OLECMDF_ values | |
963 */ | |
964 public int queryStatus(int cmd) { | |
965 | |
966 if (objIOleCommandTarget is null) { | |
98 | 967 if (objIUnknown.QueryInterface(&COM.IIDIOleCommandTarget, cast(void**)&objIOleCommandTarget) !is COM.S_OK) |
97 | 968 return 0; |
969 } | |
970 | |
98 | 971 OLECMD* olecmd = new OLECMD(); |
97 | 972 olecmd.cmdID = cmd; |
973 | |
98 | 974 auto result = objIOleCommandTarget.QueryStatus(null, 1, olecmd, null); |
97 | 975 |
976 if (result !is COM.S_OK) return 0; | |
977 | |
978 return olecmd.cmdf; | |
979 } | |
980 protected int Release() { | |
981 refCount--; | |
982 | |
983 if (refCount is 0) { | |
984 disposeCOMInterfaces(); | |
985 } | |
986 return refCount; | |
987 } | |
988 protected void releaseObjectInterfaces() { | |
989 | |
990 if (objIOleInPlaceObject!is null) | |
991 objIOleInPlaceObject.Release(); | |
992 objIOleInPlaceObject = null; | |
993 | |
994 if (objIOleObject !is null) { | |
995 objIOleObject.Close(COM.OLECLOSE_NOSAVE); | |
996 objIOleObject.Release(); | |
997 } | |
998 objIOleObject = null; | |
999 | |
1000 if (objDocumentView !is null){ | |
1001 objDocumentView.Release(); | |
1002 } | |
1003 objDocumentView = null; | |
1004 | |
1005 if (objIViewObject2 !is null) { | |
98 | 1006 objIViewObject2.SetAdvise(aspect, 0, null); |
97 | 1007 objIViewObject2.Release(); |
1008 } | |
1009 objIViewObject2 = null; | |
1010 | |
1011 if (objIOleCommandTarget !is null) | |
1012 objIOleCommandTarget.Release(); | |
1013 objIOleCommandTarget = null; | |
1014 | |
1015 if (objIUnknown !is null){ | |
1016 objIUnknown.Release(); | |
1017 } | |
1018 objIUnknown = null; | |
1019 | |
1020 COM.CoFreeUnusedLibraries(); | |
1021 } | |
1022 public bool save(File file, bool includeOleInfo) { | |
1023 if (includeOleInfo) | |
1024 return saveToStorageFile(file); | |
1025 return saveToTraditionalFile(file); | |
1026 } | |
98 | 1027 private bool saveFromContents(IStream address, File file) { |
97 | 1028 |
1029 bool success = false; | |
1030 | |
98 | 1031 IStream tempContents = address; |
97 | 1032 tempContents.AddRef(); |
1033 | |
1034 try { | |
1035 FileOutputStream writer = new FileOutputStream(file); | |
1036 | |
1037 int increment = 1024 * 4; | |
98 | 1038 LPVOID pv = COM.CoTaskMemAlloc(increment); |
1039 uint pcbWritten; | |
1040 while (tempContents.Read(pv, increment, &pcbWritten) is COM.S_OK && pcbWritten > 0) { | |
1041 byte[] buffer = new byte[ pcbWritten]; | |
1042 OS.MoveMemory(buffer.ptr, pv, pcbWritten); | |
97 | 1043 writer.write(buffer); // Note: if file does not exist, this will create the file the |
1044 // first time it is called | |
1045 success = true; | |
1046 } | |
1047 COM.CoTaskMemFree(pv); | |
1048 | |
1049 writer.close(); | |
1050 | |
1051 } catch (IOException err) { | |
1052 } | |
1053 | |
1054 tempContents.Release(); | |
1055 | |
1056 return success; | |
1057 } | |
98 | 1058 private bool saveFromOle10Native(IStream address, File file) { |
97 | 1059 |
1060 bool success = false; | |
1061 | |
98 | 1062 IStream tempContents = address; |
97 | 1063 tempContents.AddRef(); |
1064 | |
1065 // The "\1Ole10Native" stream contains a DWORD header whose value is the length | |
1066 // of the native data that follows. | |
98 | 1067 LPVOID pv = COM.CoTaskMemAlloc(4); |
1068 uint size; | |
1069 auto rc = tempContents.Read(pv, 4, null); | |
97 | 1070 OS.MoveMemory(size, pv, 4); |
1071 COM.CoTaskMemFree(pv); | |
98 | 1072 if (rc is COM.S_OK && size > 0) { |
97 | 1073 |
1074 // Read the data | |
98 | 1075 byte[] buffer = new byte[size]; |
1076 pv = COM.CoTaskMemAlloc(size); | |
1077 rc = tempContents.Read(pv, size, null); | |
1078 OS.MoveMemory(buffer.ptr, pv, size); | |
97 | 1079 COM.CoTaskMemFree(pv); |
1080 | |
1081 // open the file and write data into it | |
1082 try { | |
1083 FileOutputStream writer = new FileOutputStream(file); | |
1084 writer.write(buffer); // Note: if file does not exist, this will create the file | |
1085 writer.close(); | |
1086 | |
1087 success = true; | |
1088 } catch (IOException err) { | |
1089 } | |
1090 } | |
1091 tempContents.Release(); | |
1092 | |
1093 return success; | |
1094 } | |
1095 private int SaveObject() { | |
1096 | |
1097 updateStorage(); | |
1098 | |
1099 return COM.S_OK; | |
1100 } | |
1101 /** | |
1102 * Saves the document to the specified file and includes OLE specific information. This method | |
1103 * must <b>only</b> be used for files that have an OLE Storage format. For example, a word file | |
1104 * edited with Word.Document should be saved using this method because there is formating information | |
1105 * that should be stored in the OLE specific Storage format. | |
1106 * | |
1107 * @param file the file to which the changes are to be saved | |
1108 * | |
1109 * @return true if the save was successful | |
1110 */ | |
1111 private bool saveToStorageFile(File file) { | |
1112 // The file will be saved using the formating of the current application - this | |
1113 // may not be the format of the application that was originally used to create the file | |
1114 // e.g. if an Excel file is opened in Word, the Word application will save the file in the | |
1115 // Word format | |
1116 // Note: if the file already exists, some applications will not overwrite the file | |
1117 // In these cases, you should delete the file first (probably save the contents of the file in case the | |
1118 // save fails) | |
1119 if (file is null || file.isDirectory()) return false; | |
1120 if (!updateStorage()) return false; | |
1121 | |
1122 // get access to the persistent storage mechanism | |
98 | 1123 IPersistStorage permStorage; |
1124 if (objIOleObject.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&permStorage) !is COM.S_OK) return false; | |
97 | 1125 try { |
98 | 1126 IStorage storage; |
1127 wchar* path = StrToWCHARz(file.getAbsolutePath()); | |
97 | 1128 int mode = COM.STGM_TRANSACTED | COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE; |
98 | 1129 int result = COM.StgCreateDocfile(path, mode, 0, &storage); //Does an AddRef if successful |
97 | 1130 if (result !is COM.S_OK) return false; |
1131 try { | |
98 | 1132 if (COM.OleSave(permStorage, storage, false) is COM.S_OK) { |
97 | 1133 if (storage.Commit(COM.STGC_DEFAULT) is COM.S_OK) { |
1134 return true; | |
1135 } | |
1136 } | |
1137 } finally { | |
1138 storage.Release(); | |
1139 } | |
1140 } finally { | |
1141 permStorage.Release(); | |
1142 } | |
1143 return false; | |
1144 } | |
1145 /** | |
1146 * Saves the document to the specified file. This method must be used for | |
1147 * files that do not have an OLE Storage format. For example, a bitmap file edited with MSPaint | |
1148 * should be saved using this method because bitmap is a standard format that does not include any | |
1149 * OLE specific data. | |
1150 * | |
1151 * @param file the file to which the changes are to be saved | |
1152 * | |
1153 * @return true if the save was successful | |
1154 */ | |
1155 private bool saveToTraditionalFile(File file) { | |
1156 // Note: if the file already exists, some applications will not overwrite the file | |
1157 // In these cases, you should delete the file first (probably save the contents of the file in case the | |
1158 // save fails) | |
1159 if (file is null || file.isDirectory()) | |
1160 return false; | |
1161 if (!updateStorage()) | |
1162 return false; | |
1163 | |
98 | 1164 IStream stream; |
97 | 1165 // Look for a CONTENTS stream |
98 | 1166 if (tempStorage.OpenStream(("CONTENTS"w).ptr, null, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, &stream) is COM.S_OK) //$NON-NLS-1$ |
1167 return saveFromContents(stream, file); | |
97 | 1168 |
1169 // Look for Ole 1.0 object stream | |
98 | 1170 if (tempStorage.OpenStream(("\1Ole10Native"w).ptr, null, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, &stream) is COM.S_OK) //$NON-NLS-1$ |
1171 return saveFromOle10Native(stream, file); | |
97 | 1172 |
1173 return false; | |
1174 } | |
1175 private int Scroll(int scrollExtant) { | |
1176 return COM.S_OK; | |
1177 } | |
98 | 1178 void setBorderSpace(RECT* newBorderwidth) { |
1179 borderWidths = *newBorderwidth; | |
97 | 1180 // readjust size and location of client site |
1181 Rectangle area = frame.getClientArea(); | |
1182 setBounds(borderWidths.left, borderWidths.top, | |
1183 area.width - borderWidths.left - borderWidths.right, | |
1184 area.height - borderWidths.top - borderWidths.bottom); | |
1185 setObjectRects(); | |
1186 } | |
1187 private void setExtent(int width, int height){ | |
1188 // Resize the width and height of the embedded/linked OLENatives object | |
1189 // to the specified values. | |
1190 | |
1191 if (objIOleObject is null || isStatic || inUpdate) return; | |
98 | 1192 SIZE* currentExtent = getExtent(); |
97 | 1193 if (width is currentExtent.cx && height is currentExtent.cy) return; |
1194 | |
98 | 1195 SIZE* newExtent = new SIZE(); |
97 | 1196 newExtent.cx = width; newExtent.cy = height; |
1197 newExtent = xFormPixelsToHimetric(newExtent); | |
1198 | |
1199 // Get the server running first, then do a SetExtent, then show it | |
98 | 1200 bool alreadyRunning = cast(bool) COM.OleIsRunning(objIOleObject); |
97 | 1201 if (!alreadyRunning) |
98 | 1202 COM.OleRun(objIOleObject); |
97 | 1203 |
1204 if (objIOleObject.SetExtent(aspect, newExtent) is COM.S_OK){ | |
1205 inUpdate = true; | |
1206 objIOleObject.Update(); | |
1207 inUpdate = false; | |
1208 if (!alreadyRunning) | |
1209 // Close server if it wasn't already running upon entering this method. | |
1210 objIOleObject.Close(COM.OLECLOSE_SAVEIFDIRTY); | |
1211 } | |
1212 } | |
1213 public void setIndent(Rectangle newIndent) { | |
1214 indent.left = newIndent.x; | |
1215 indent.right = newIndent.width; | |
1216 indent.top = newIndent.y; | |
1217 indent.bottom = newIndent.height; | |
1218 } | |
1219 private void setObjectRects() { | |
1220 if (objIOleInPlaceObject is null) return; | |
1221 // size the object to fill the available space | |
1222 // leave a border | |
98 | 1223 RECT* rect = getRect(); |
97 | 1224 objIOleInPlaceObject.SetObjectRects(rect, rect); |
1225 } | |
1226 | |
1227 private int ShowObject() { | |
1228 /* Tells the container to position the object so it is visible to | |
1229 * the user. This method ensures that the container itself is | |
1230 * visible and not minimized. | |
1231 */ | |
1232 return COM.S_OK; | |
1233 } | |
1234 /** | |
1235 * Displays a dialog with the property information for this OLE Object. The OLE Document or | |
1236 * ActiveX Control must support the ISpecifyPropertyPages interface. | |
1237 * | |
1238 * @param title the name that will appear in the titlebar of the dialog | |
1239 */ | |
212
ab60f3309436
reverted the char[] to String and use the an alias.
Frank Benoit <benoit@tionex.de>
parents:
162
diff
changeset
|
1240 public void showProperties(String title) { |
97 | 1241 |
1242 // Get the Property Page information from the OLE Object | |
98 | 1243 ISpecifyPropertyPages objISPP; |
1244 if (objIUnknown.QueryInterface(&COM.IIDISpecifyPropertyPages, cast(void**)&objISPP) !is COM.S_OK) return; | |
1245 CAUUID* caGUID = new CAUUID(); | |
1246 auto result = objISPP.GetPages(caGUID); | |
97 | 1247 objISPP.Release(); |
1248 if (result !is COM.S_OK) return; | |
1249 | |
1250 // create a frame in which to display the pages | |
98 | 1251 wchar* chTitle = null; |
97 | 1252 if (title !is null) { |
98 | 1253 chTitle = StrToWCHARz(title); |
97 | 1254 } |
98 | 1255 result = COM.OleCreatePropertyFrame(frame.handle, 10, 10, chTitle, 1, &objIUnknown, caGUID.cElems, caGUID.pElems, COM.LOCALE_USER_DEFAULT, 0, null); |
97 | 1256 |
1257 // free the property page information | |
1258 COM.CoTaskMemFree(caGUID.pElems); | |
1259 } | |
1260 private bool updateStorage() { | |
1261 | |
1262 if (tempStorage is null) return false; | |
1263 | |
98 | 1264 IPersistStorage iPersistStorage; |
1265 if (objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&iPersistStorage) !is COM.S_OK) return false; | |
97 | 1266 |
98 | 1267 auto result = COM.OleSave(iPersistStorage, tempStorage, true); |
97 | 1268 |
1269 if (result !is COM.S_OK){ | |
1270 // OleSave will fail for static objects, so do what OleSave does. | |
98 | 1271 COM.WriteClassStg(tempStorage, objClsid); |
1272 result = iPersistStorage.Save(tempStorage, true); | |
97 | 1273 } |
1274 | |
1275 tempStorage.Commit(COM.STGC_DEFAULT); | |
98 | 1276 result = iPersistStorage.SaveCompleted(null); |
97 | 1277 iPersistStorage.Release(); |
1278 | |
1279 return true; | |
1280 } | |
98 | 1281 private SIZE* xFormHimetricToPixels(SIZE* aSize) { |
97 | 1282 // Return a new Size which is the pixel transformation of a |
1283 // size in HIMETRIC units. | |
1284 | |
98 | 1285 auto hDC = OS.GetDC(null); |
97 | 1286 int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x |
1287 int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y | |
98 | 1288 OS.ReleaseDC(null, hDC); |
97 | 1289 int cx = Compatibility.round(aSize.cx * xppi, 2540); // 2540 HIMETRIC units per inch |
1290 int cy = Compatibility.round(aSize.cy * yppi, 2540); | |
98 | 1291 SIZE* size = new SIZE(); |
97 | 1292 size.cx = cx; |
1293 size.cy = cy; | |
1294 return size; | |
1295 } | |
98 | 1296 private SIZE* xFormPixelsToHimetric(SIZE* aSize) { |
97 | 1297 // Return a new size which is the HIMETRIC transformation of a |
1298 // size in pixel units. | |
1299 | |
98 | 1300 auto hDC = OS.GetDC(null); |
97 | 1301 int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x |
1302 int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y | |
98 | 1303 OS.ReleaseDC(null, hDC); |
97 | 1304 int cx = Compatibility.round(aSize.cx * 2540, xppi); // 2540 HIMETRIC units per inch |
1305 int cy = Compatibility.round(aSize.cy * 2540, yppi); | |
98 | 1306 SIZE* size = new SIZE(); |
97 | 1307 size.cx = cx; |
1308 size.cy = cy; | |
1309 return size; | |
1310 } | |
1311 } | |
98 | 1312 |
1313 class _IAdviseSinkImpl : IAdviseSink { | |
1314 | |
1315 OleClientSite parent; | |
1316 this(OleClientSite p) { parent = p; } | |
1317 extern (Windows): | |
1318 // interface of IUnknown | |
1319 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); } | |
1320 ULONG AddRef() { return parent.AddRef(); } | |
1321 ULONG Release() { return parent.Release(); } | |
1322 | |
1323 // interface of IAdviseSink | |
1324 void OnDataChange(FORMATETC *pFormatetc,STGMEDIUM *pStgmed) {return COM.S_OK; } | |
1325 void OnViewChange(DWORD dwAspect, LONG lindex) {return COM.S_OK; } | |
1326 void OnRename(IMoniker pmk) {return COM.S_OK; } | |
1327 void OnSave() {return COM.S_OK; } | |
1328 void OnClose() {return COM.S_OK; } | |
1329 } | |
1330 | |
1331 class _IOleClientSiteImpl : IOleClientSite { | |
1332 | |
1333 OleClientSite parent; | |
1334 this(OleClientSite p) { parent = p; } | |
1335 extern (Windows): | |
1336 // interface of IUnknown | |
1337 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); } | |
1338 ULONG AddRef() { return parent.AddRef(); } | |
1339 ULONG Release() { return parent.Release(); } | |
1340 | |
1341 // interface of IOleClientSite | |
1342 HRESULT SaveObject() { if(parent) parent.updateStorage(); return COM.S_OK; } | |
1343 HRESULT GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, IMoniker * ppmk ) {return COM.E_NOTIMPL; } | |
1344 HRESULT GetContainer( IOleContainer* ppContainer ) { return parent.GetContainer(ppContainer);} | |
1345 HRESULT ShowObject() { | |
1346 /* Tells the container to position the object so it is visible to | |
1347 * the user. This method ensures that the container itself is | |
1348 * visible and not minimized. | |
1349 */ | |
1350 return COM.S_OK; | |
1351 } | |
1352 HRESULT OnShowWindow(BOOL fShow ) {return COM.S_OK; } | |
1353 HRESULT RequestNewObjectLayout() {return COM.E_NOTIMPL; } | |
1354 } | |
1355 | |
1356 class _IOleDocumentSiteImpl : IOleDocumentSite { | |
1357 | |
1358 OleClientSite parent; | |
1359 this(OleClientSite p) { parent = p; } | |
1360 extern (Windows): | |
1361 // interface of IUnknown | |
1362 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); } | |
1363 ULONG AddRef() { return parent.AddRef(); } | |
1364 ULONG Release() { return parent.Release(); } | |
1365 | |
1366 // interface of IOleDocumentSite | |
1367 HRESULT ActivateMe(IOleDocumentView pViewToActivate) { return parent.ActivateMe(pViewToActivate);} | |
1368 } | |
1369 | |
1370 class _IOleInPlaceSiteImpl : IOleInPlaceSite { | |
1371 OleClientSite parent; | |
1372 this(OleClientSite p) { parent = p; } | |
1373 extern (Windows): | |
1374 // interface of IUnknown | |
1375 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); } | |
1376 ULONG AddRef() { return parent.AddRef(); } | |
1377 ULONG Release() { return parent.Release(); } | |
1378 | |
1379 // interface of IOleWindow | |
1380 HRESULT GetWindow( HWND* phwnd ) { return parent.GetWindow(phwnd); } | |
1381 HRESULT ContextSensitiveHelp( BOOL fEnterMode ) {return COM.S_OK; } | |
1382 | |
1383 // interface of IOleInPlaceSite | |
1384 HRESULT CanInPlaceActivate() { return parent.CanInPlaceActivate();} | |
1385 HRESULT OnInPlaceActivate() { return parent.OnInPlaceActivate(); } | |
1386 HRESULT OnUIActivate() { return parent.OnUIActivate(); } | |
1387 HRESULT GetWindowContext( IOleInPlaceFrame * ppFrame, IOleInPlaceUIWindow * ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo ) { | |
1388 return parent.GetWindowContext(ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo); | |
1389 } | |
1390 HRESULT Scroll( SIZE scrollExtant ) {return COM.S_OK; } | |
1391 HRESULT OnUIDeactivate( BOOL fUndoable ) { return parent.OnUIDeactivate(fUndoable);} | |
1392 HRESULT OnInPlaceDeactivate() { return parent.OnInPlaceDeactivate();} | |
1393 HRESULT DiscardUndoState() {return COM.E_NOTIMPL; } | |
1394 HRESULT DeactivateAndUndo() {return COM.E_NOTIMPL; } | |
1395 HRESULT OnPosRectChange( LPCRECT lprcPosRect) { return parent.OnPosRectChange(lprcPosRect);} | |
1396 } | |
1397 | |
1398 class _IUnknownImpl : IUnknown | |
1399 { | |
1400 | |
1401 OleClientSite parent; | |
1402 this(OleClientSite p) { parent = p; } | |
1403 extern (Windows): | |
1404 // interface of IUnknown | |
1405 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); } | |
1406 ULONG AddRef() { return parent.AddRef(); } | |
1407 ULONG Release() { return parent.Release(); } | |
1408 } | |
1409 | |
1410 | |
1411 | |
1412 |