|
lcarriere wrote:
Is there a way for me to work with this instance in a Type Library using reflection.
Assemblies are not type libraries, which describe COM types. You can't reflect COM types in .NET, though you can reflect their RCWs (runtime callable wrappers), but that's definitely not the same thing. Type metadata and IL modules are stored in assemblies.
If you want to reflect the singleton in such a way that when you access a property then you shouldn't have a problem if you follow the recommend pattern, in which each property gets an instance - which creates the instance if not created already - and returns a value from the instance using the private instance field. The following example also uses the double-checked locking method, which is the safest way of creating a singleton:
using System;
class Singleton
{
static object sync = new object();
static Singleton instance;
int serialNumber;
Singleton()
{
}
static Singleton Instance
{
get
{
if (instance == null)
lock (sync)
if (instance == null)
instance = new Singleton();
return instance;
}
}
public static int SerialNumber
{
get
{
return ++Instance.serialNumber;
}
}
} Notice how the SerialNumber property uses the static private Instance property, which will create a single instance if necessary. When you reflect the static property SerialNumber and instance gets created.
To reflect static members you need to use the overload that allows you to specify a BindingFlags , providing to it at least BindingFlags.Static . The default implementations like GetProperty search for public instance properties, not static and non-public properties. Other than that you would reflect it as you normally would reflect a type with an assembly.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
I am sorry I meant to say Class Library (to much rum and eggnog last night - just kidding).
Thanks this helps a lot. Do you have a small example of reflecting a static method?
|
|
|
|
|
If you look at the Type.GetMethods documentation - along with the BindingFlags enumeration documentation, it's quite easy:
Type t = typeof(Singleton);
MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static); This will gather public static methods. For more options, see the BindingFlags enumeration documentation in the .NET Framework SDK, which is installed by default with VS.NET, can be installed stand-alone from http://msdn.microsoft.com/netframework[^], or is available online at http://msdn.microsoft.com/library[^].
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
yes sorry, I should have replied sooner. I discovered the methods you mentioned and it is working perfectly.
Thanks for your help!
|
|
|
|
|
I posted to this board almost a month ago, and no one had a response for any of my questions. Can anyone offer any comments on these topics?
Thanks much.
***********************************
(from 1 December 2004)
I'm a total newbie in the land of C#, Visual Studio, .NET, and all-things-Microsoft. I'm trying to do a number of things with a C# application that has a builtin web browser (AxSHDocVw.AxWebBrowser). Most of the code I've inherited from someone else who knew a lot more about this stuff than I do, so I'm barely treading water at the moment.
If anyone can help shed some light on the following things, I'd be very grateful.
1) Is there a way to control the browser to not display until DocumentComplete has been called (i.e. READYSTATE_COMPLETE)? I want the page to *not* show anything until it's fully loaded, and can't figure out how to do this.
2) Is there a way to modify the UserAgent sent by the browser? Some of the docs have suggested (at least in C++ land) that in the Navigate() method I can postpend to the header argument to add things, such as the user agent. However, I'm not sure that a) this works, or b) what the appropriate syntax is in calling this from C#. I've tried just throwing in a string argument, but am not 100% sure of the syntax, nor did it seem to affect anything.
I've also seen:
http://support.microsoft.com/kb/q183412/
but don't know how I can do something similar in my project.
3) I've tried, unsuccessfully, to make a call to create a desktop shortcut using IWshRuntimeLibrary. Here's my code:
WshShell shell = new WshShell();
IWshShortcut link = (IWshShortcut)shell.CreateShortcut(title);
link.TargetPath = url;
link.Save();
This always throws an exception, even when the app is being run by an administrator account. It's a System.Runtime.InteropServices.COMException, and the message is just "Exception occurred." I took this code directly from:
http://www.codeproject.com/dotnet/shelllink.asp
Any idea what might be going wrong here?
Thanks much. Sorry if these questions are too broad. Let me know if I can be more specific.
|
|
|
|
|
dkarlton wrote:
I posted to this board almost a month ago, and no one had a response for any of my questions.
This is a community forum - not a managed newsgroup. Older messages sometimes slip through the cracks as there are times us regulars aren't around to answer questions.
dkarlton wrote:
1) Is there a way to control the browser to not display until DocumentComplete has been called (i.e. READYSTATE_COMPLETE)? I want the page to *not* show anything until it's fully loaded, and can't figure out how to do this.
No. The browser renders objects - including the DOM as certain elements are loaded - as they are read.
dkarlton wrote:
2) Is there a way to modify the UserAgent sent by the browser? ...
While the documentation is not clear, it does state that the second-to-last parameter (PostData ) is a SAFEARRAY (native type), which is a common array type in COM (since native arrays imply no bounds; SAFEARRAY s do). The CLR will marshal a string[] array as a SAFEARRAY but you need to specify UnmanagedType.SafeArray in the MarshalAsAttribute for the parameter. Without defining the interface yourself (instead of using the imported RCW) you'll have to take a chance.
Define a string[] array like so:
string[] headers = new string[] {"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US)"}; Then pass headers as the last parameter. It's already a reference type so don't try to marshal it as a pointer. Problems will definitely arise (like, perhaps, an AV exception) if you do.
The important thing is to understand marshaling managed and native types. Read Interop Marshaling[^] in the .NET Framework SDK for more information.
dkarlton wrote:
3) I've tried, unsuccessfully, to make a call to create a desktop shortcut using IWshRuntimeLibrary. Here's my code:
A quick search[^] on "WshShell" returned the following article as the first result: Creating Shell Links (Shortcuts) in .NET Programs Using WSH
[^]. Take a look at the sample project for details, and be sure to read the documentation for the native interfaces. With that information and the marshaling information I linked above it's quite easy.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Thanks for the info, incredibly helpful.
1) If it's not possible to suspend layout during document load of the browser control, can you recommend a good way to "hide" it until it's finished? Currently, I am using this:
<br />
[DllImport("User32")] <br />
private static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);<br />
<br />
private bool FreezePainting { <br />
set { <br />
if (value && IsHandleCreated && this.Visible) <br />
SendMessage(Handle, WM_SETREDRAW, 0, 0); <br />
if (!value) { SendMessage(Handle, WM_SETREDRAW, 1, 0); <br />
Invalidate(true);<br />
} <br />
} <br />
}<br />
I then just call FreezePainting at NavigateComplete and DocumentComplete. The problem is that the app is essentially "dead" to input during the load. Any novel ideas?
2) I'm a little unclear on how to correctly marshal the argument, for overriding the user agent. I wasn't sure if I should just pass the string[] as the last argument, or if I need to additionally declare marshaling. I tried just simply passing the string[] argument, but it seemed to have no effect. I assume I need to do more than this. Although I think I understand conceptually what is required to bridge the gap between C# code and unmanaged libraries, I'm not sure how to actually do it.
3) I got the shortcut creation to work. The link you gave was actually the same one I had indicated before, as well. The problem I had been having the entire time is that the link title apparently must end with ".lnk". I wasn't aware of this, and never saw this in any documentation. It was just throwing an exception. So one problem down...
Thanks. Appreciate the help!
David
|
|
|
|
|
Regarding #2 you may actually need to manually declare the IWebBrowser2 interface - or at least a skeleton interface with the correct method signature and DispIdAttribute , not to mention the InterfaceTypeAttribute (it inherits from IDispatch , remember), GuidAttribute , and ComImportAttribute .
If you don't want the control visible while loading, set the AxHost.Visible to false . You could also put a control in its place.
Otherwise, what you're doing seems fine but - as you've noticed - blocks the application from input. Off the top of my head I really don't have any better ideas.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
I forgot to mention in my last post (and am posting another message instead of modifying my previous one so that you get an automatic notification email again since it's an older post) that the reason for declaring IWebBrowser2 yourself is so that you can use the MarshalAsAttribute for the last two parameters with the value UnmanagedType.SafeArray . You should also set the MarshalAsAttributeSafeArraySubType appropriately as whichever VarEnum value(s) you need, like VarEnum.VT_LPWSTR when marshaling the strings as CharSet.Unicode , for example.
See the .NET Framework SDK documentation for MarshalAsAttribute and its fields and related enumerations mentioned above for more information.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
For overriding the user agent, I am wondering if I actually need to do this from within the BeforeNavigate2(object sender, AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2Event e) method. If the user clicks on a link from within the browser control, the Navigate method is not exercised. Would it be possible to modify the DWebBrowserEvents2_BeforeNavigate2Event.header variable in this case? Or is there a better solution to this? In the case of modifying the header field of the event, what would need to be done for marshaling etc.? Would I need to declare an unmanaged type for the event class itself in order to modify its header field?
|
|
|
|
|
Give it a try. Since the parameters are pointers to VARIANTs that is a SAFEARRAY you would marshal these using UnmanagedType.SafeArray and declare the parameters as a string[] (which is already a reference type). You can try to change the data in there but whether or not the WebBrowser uses it after firing the BeforeNavigator2 event is another question.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Still looking into the user agent. I've also tried seeing if it's somehow possible to override the window.navigator.userAgent DHTML property, to no avail. The BeforeNavigate2 method by default has a "null" value for the header property of the event (i.e. AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2Event.headers == null ). So, I don't think that changing it or setting it there will make a difference (although I haven't tried yet, as I'm still trying to figure out how to write the code for marshaling). And since we aren't using the Navigate method (rather, relying on the user to click on links), I don't see how to modify the user agent, yet. We'll figure something out... I guess I need help from an IE SDK guru. Dunno.
The reason that we're trying to hide the browser window (question #1 from before) during document loading is that we need to rescale the page, by setting the body.style.zoom property once the page has loaded. This begs the question of whether or not it's possible to just automatically set the zoom property somehow (in advance), without having to invoke it once the page is loaded (which is what we're doing now, after DocumentComplete). It would be nice to be able to just have the zoom property "preset", without having to invoke it after the fact, so that the page is always scaled, even during loading (if that's even possible). Maybe this is more of a DHTML question, I don't really know.
Also, in the alternative where you suggest to put another control on top of the browser while it's loading, what exactly did you have in mind? We don't want the browser to "flash" or anything between pages.
Thanks for your help so far, it's been quite informative!
|
|
|
|
|
I've been doing some more investigation to try to see how to avoid my IE web browser from showing the layout while a page is downloading, so that it waits until DocumentComplete before displaying the page.
I've noticed that in C++ world, there's a flag DLCTL_SILENT that can be set on the pvarResult in IDispatch::Invoke. This flag says "No user interface will be displayed during downloads." Needless to say, this caught my attention. (If someone out there knows offhand that this is in fact *not* doing what I hope it's doing, please chime in.)
My problem now is that I can't figure out how to properly implement this in my C# application. Any ideas?
Thanks.
David
|
|
|
|
|
When I enable VisualStyles in my Application I loose all the images on all the toolbarbuttons of my app in runtime. The problem is solved when I disable visualstyles.
This only happens in runtime as I can see the images perfectly in the designer.
I'm currently using bmps 24x24 pixels and
24 BPP. Transparent color of the ImageList is set to White.
Anybody knows why this is happening?
|
|
|
|
|
Are you calling Application.DoEvents after Application.EnableVisualStyles and before Application.Run ? If you don't, problem like this will arise due to timing issues. A bare-bones entry-point should look like this (for example):
static void Main()
{
Application.EnableVisualStyles();
Application.DoEvents();
Application.Run(new Form1());
}
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Thanks a lot Heath, that solved the problem
|
|
|
|
|
Maybe I wasnt clear enough in my last thread:
I want to use the API function SendMessage in my .NET CF apllication.
I use the following code to get the handle of my TextBox window:
[DllImport("coredll.dll")]
internal extern static IntPtr GetCapture();
this.Capture = true;
hwnd = GetCapture();
this.Capture = false;
I want to send messages in order to extend the functionality of my TextBox.
I use:
[DllImport("coredll.dll")]
internal extern static int SendMessage(IntPtr Hwnd, int Msg, int WParam, int LParam);
SendMessage(this.hwnd, (int)0x0300/*WM_CUT*/, 0, 0);
This does not cut the text in my TextBox.
I have read all through the .NET CF and could not find the reason for this.
Any other p/invoke I use works fine (like GetCapture) but the SendMessage doesnt.
Please help...
Thanks.
avivhal
|
|
|
|
|
Seems kind of convoluted. Are you just trying to move some text from a textbox to the clipboard?
Anyway, if you are doing this in an event handler that may be the problem; have you tried PostMessage() instead?
Matt Gerrans
|
|
|
|
|
Thanks for the answer.
I tried PostMessage as well. It does not work.
I do not do it in an event handler of a menu.
My goal is to create a more robust editor then TextBox(that’s all there is in the .net CF, no RichTextBox). Therefore I build an extended TextBox with cut,copy,paste and more.
My other problem is that when I try to add text programmatically:
int len = textBoxTerminal.Text.Length;
textBoxTerminal.SelectionStart = len;
textBoxTerminal.SelectionLength = len;
textBoxTerminal.SelectedText = (string)StringToAdd;
the caret always positions itself in the beginning of the TextBox's Text.
I can reposition it to the end and scroll, but this causes the TextBox to flicker. I thought PostMessage will help solving this, but I cannot test it for the Since PostMesage does not work for me.
Hope you have an answer for this...
Thanks.
avivhal
|
|
|
|
|
What is the return code for SendMessage ? Check this against the errors in winerror.h.
You should also set the DllImportAttribute.CharSet field to CharSet.Auto . There is actually no SendMessage function, but SendMessageA (ANSI) and SendMessageW (Wide-char, or Unicode). The Windows .NET CE platform is actually Unicode, so you could P/Invoke SendMessageW and set DllImportAttribute.EntryPoint to "SendMessageW" (since DllImportAttribute.ExactSpelling is not supported for the .NET CF).
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Neither DllImportAttribute.CharSet nor SendMessageW worked.
I did get it to work though (somehow)...
I took the declarations I have of SendMessage(I have a few overloads) :
[DllImport("coredll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
and wrapped them in a separate class.
Then I called them as this class's static members and it works!
I do not understand why would this solve the problem though...?
Maybe the problem was that they were members of a TextBox (Form) derived class and this caused congestion problems with the Form’s own messages?
I wish I had the OS source code so I could check this;)
avivhal
|
|
|
|
|
How were you doing it before? C# does not support functions - only methods. They would've had to have been members of a class before or else you couldn't have even compiled your source file.
BTW - those last two parameters are process-dependent types and should be IntPtr . If you're needing to pass pointers to structs or char arrays (strings), you can define overloads that would amount to a pointer, such as simply string or ref MyStruct . int is an Int32 in C# and will always be 32 bits. If you ever hope to port this - whether the source or binary - you'll need to change it anyway.
External methods must always be static, too, but you declared them statically before, did you not?
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
They were static members of the my TextBoxEx class before.
All I did was build a new class and pass the methods to be static members of the new class. then call them as the new class methods.
e.g. if my old class was Aclass and the new Bclass then in Aclass I call:
Bclass.SendMessage(...);
I have a few overloads such as
[DllImport("coredll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, String lParam);
[DllImport("coredll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, byte[] lParam);
that take addresses (pointers). I only use :
[DllImport("coredll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
to call with 0 lparam and wparam thus:
Bclass.SendMessage(this.Handle, (int)ClipboardMessage.WM_UNDO, 0, 0);
I probably should use 2 pointers (IntPtr) instead and lock the IntPtr for the GC before calling this method?
Thanks,
Aviv.
avivhal
|
|
|
|
|
On what class they're defined shouldn't matter, but perhaps some of your overloads were conflicting.
With value types - like int - you do not need to pin them (see the GCHandle class, BTW). Reference types may be moved by the GC on the heap, but it depends how the message handler uses the data; you may not need to pin the memory. Strings are reference types but this data is typically used synchronously with SendMessage (PostMessage , on the other hand, is a different story). When passing addresses of reference objects (as IntPtr , or just a GCHandle which works, too, as well as a HandleRef ) you should pin them.
For robust code, never use fixed-size integers for the WPARAM and LPARAM . Always use IntPtr . For 0, just use IntPtr.Zero and to wrap an int or long use new IntPtr(int) or new IntPtr(long) , respectively.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Can anyone tell me how to print text and images within a rich text box?
Thanks,
Sterling
|
|
|
|
|