In a terminal services/citrix environment, should I call
Application.EnableVisualStyles() in my .NET 3.5 WinForms app when my program
starts? Or, is it better to refrain from doing that?
I am looking for the option that gives the best performance, and do not need any controls drawn with
themes.
Visual styles are the colors, fonts, and other visual elements that form an operating system theme. Controls will draw with visual styles if the control and the operating system support it. To have an effect, EnableVisualStyles() must be called before creating any controls in the application; typically, EnableVisualStyles() is the first line in the Main function.
So, if you need to have your application look in line with the current OS theme, you need to call this. If the classic Windows look is enough for you, you can skip this. I personally never enable visual styles for my server-only apps (like control panels, etc.).
Below is a configurator tool without the visual styles enabled. It's good looking for me this way so EnableVisualStyles was skipped:
A quick look into Application.EnableVisualStyles() method with reflector revealed below code in the method EnableVisualStyles -> EnableVisualStylesInternal -> CreateActivationContext:
if (!contextCreationSucceeded && OSFeature.Feature.IsPresent(OSFeature.Themes))
{
enableThemingActivationContext = new ACTCTX();
enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX));
enableThemingActivationContext.lpSource = dllPath;
enableThemingActivationContext.lpResourceName = (IntPtr) nativeResourceManifestID;
enableThemingActivationContext.dwFlags = 8;
hActCtx = CreateActCtx(ref enableThemingActivationContext);
contextCreationSucceeded = hActCtx != new IntPtr(-1);
}
If OSFeature.Feature.IsPresent(OSFeature.Themes) returns false, EnableVisualStyles has absolutely no effect so calling it or not makes no difference.
Related
I am building a UI using pure Direct2D and C# with SharpDX.
This UI is meant to be user-friendly and good-looking, while being efficient.
For the sake of demonstration, I built a prototype using hacky undocumented APIs (see this question), but in no way I am going to production with this, being backward-compatibility the first and foremost reason:
var accent = new User32.AccentPolicy { AccentState = AccentState };
int accentStructSize = Marshal.SizeOf(accent);
// allocate space for the struct
IntPtr accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
// set composition data
var data = new User32.WindowCompositionAttributeData {
Attribute = User32.WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = accentStructSize,
Data = accentPtr
};
// change window composition attributes and release resources
User32.SetWindowCompositionAttribute(Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
I know the instant response to this is to use WPF, but I'm fairly limited to raw Direct2D calls, as I'm intending to move all the UI logic to a DLL for injection in DirectX apps (which, albeit not being sure how I'm going to do this, is out of the scope of this question.)
On Windows 8.1, there is DirectComposition, which enables efficient alpha-blending on top of transparent windows.
But there's no such thing in Windows Vista and 7 (even with the Platform Update).
Is there a way I can use pure, non-hacky Direct2D/DirectX code to make this UI work across all Windows versions (preferably Vista SP2 upwards)?
I'm working on a interactive rendering software using opengl in sdl written in c++.
The project evolving, I wanted to have a HIM/GUI to manipulate my rendering engine.
So I started to search some easy/fast HIM coding ways to do it.
Finnaly I decided to use winforms and c# to create HIM, because its offer a way to design and code easily a HIM.
At first i started to create an hybrid dll with native and managed c++. OK.
After I try to use this dll inside a c# application. OK.
Now my goal is: insert the opengl rendering inside the winforms application.
My questions are:
Can I bind my SDLcontext/SDLwindows(C++) to a winforms object?
Can I bind a c# bitmap to an array of byte from my dll ? (aim to update pixels of it by the dll)
if ok: do I have to call a function to refresh my GUI(winforms) on pixel change ?
Do you think it will be interesting to drop SDL and use only winforms for this kind of work ?
Any suggestion ?
EDIT: add information about my investigation
Thanks to Lawrence Kok I pursue my research.
So I tried to bind my SDL windows to a Panel form
private void LaunchEngine(string str)
{
unsafe
{
byte[] bytes = Encoding.ASCII.GetBytes(str);
sbyte[] sbyt = (sbyte[])(Array)bytes;
fixed (sbyte* p = sbyt)
{
// Engine is a managed class that bridge my c++ to c#
// all it's function are static
Engine.LOAD_CONTENT_FROM_FILE(p);
Engine.PRINTCONFIGURATION();
if (Engine.LOAD_ENGINE_DATA() && Engine.INITIALISE_ENGINE_DATA())
{
// Bind attempt here
_SdlWindowHandle = Engine.GETHANDLE();
SetWindowPos(_SdlWindowHandle, this.Handle, 0, 0, 0, 0, (SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_SHOWWINDOW));
// Make the SDL Window the child of our Panel
SetParent(_SdlWindowHandle, m_SdlPanel.Handle);
ShowWindow(_SdlWindowHandle, ShowWindowCommand.SW_SHOWNORMAL);
// In futur i will put this loop in another thread
// but for now I'm trying to validate my prototype
for (; ; )
{
Engine.UPDATE_ENGINE_DATA();
Engine.DRAW_ENGINE_DATA();
}
}
}
}
Actually, the change the parent of my sdl windows, close it, and my engine is running, but my panel is completely blank.
I think I'm missing something here but i can't figured what.
here is how i get the SDL window handle (from SDL2)
// coming from c++ native library
// and represent by Engine.GETHANDLE();
// from managed c++ lib
HWND SDLWindowManager::GetHandle()
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
/*if (SDL_GetWMInfo(&info) < 0)
return 0;*/
SDL_GetWindowWMInfo(_mainWindow, &info);
return info.info.win.window;
}
EDIT: problem solved
I forget to add the panel to winforms control:
public Form1()
{
InitializeComponent();
m_SdlPanel = new Panel();
m_SdlPanel.Size = new Size(512, 512);
m_SdlPanel.Location = new Point(0, 0);
Controls.Add(m_SdlPanel);
}
Given that your target platform is Windows, there is a very easy way to insert your opengl rendering into your windows form application. You can simply make a window with your favorite package of choice, sdl, sfml, plain winapi code. When you obtain the handle of the window in question, just change the style of the window so that it becomes a child window, and put it as a child window of your window of choice. As for the parent window, what I like to do is subclass special panel-type control for this purpose.
After that you can just use the composition of the controls as normal. Only the airspace problems might influence the presentation (https://msdn.microsoft.com/en-us/library/aa970688%28v=vs.110%29.aspx).
I have problem with memory leak in webBrowser control.
I have found this thread:
How to get around the memory leak in the .NET Webbrowser control?
and this:
//dispose to clear most of the references
this.webbrowser.Dispose();
BindingOperations.ClearAllBindings(this.webbrowser);
//using reflection to remove one reference that was not removed with the dispose
var field = typeof(System.Windows.Window).GetField("_swh", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var valueSwh = field.GetValue(mainwindow);
var valueSourceWindow = valueSwh.GetType().GetField("_sourceWindow", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(valueSwh);
var valuekeyboardInput = valueSourceWindow.GetType().GetField("_keyboardInputSinkChildren", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(valueSourceWindow);
System.Collections.IList ilist = valuekeyboardInput as System.Collections.IList;
lock(ilist)
{
for (int i = ilist.Count-1; i >= 0; i--)
{
var entry = ilist[i];
var sinkObject = entry.GetType().GetField("_sink", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (object.ReferenceEquals(sinkObject.GetValue(entry), this.webbrowser.webBrowser))
{
ilist.Remove(entry);
}
}
}
But I'm using Windows.Forms no WPF window and i have problem with converting this code to my needs. Can somebody help me?
We have used Chromium in a couple of applications. This allowed us to run HTML 5 in WinXP. Since the webBrowser control uses the installed IE of the OS you can't use most of the better HTML/Javascript. Microsoft doesn't support WinXP's IE so the application only can access older versions of IE.
If you use the CEFSharp version of Chromium you can even compile in further mods and aids for your navigation which gives you improved embedded communication that isn't supported by IE.
The code is really simple and there are several examples but just look:
InitializeComponent();
Text = "CefSharp";
web_view = new WebView("https://github.com/perlun/CefSharp", new BrowserSettings());
web_view.Dock = DockStyle.Fill;
toolStripContainer.ContentPanel.Controls.Add(web_view);
//even setup the console to log to a Textbox for debugging by setting up a Handler.
web_view.ConsoleMessage += new CefSharp.ConsoleMessageEventHandler(ConsoleMessageHandler);
We faced that problem some time ago... to no avail.
To work around the problem and keep our application's memory consumption at a reasonable level we decided to split our application in two kind of processes, one for the main window and N child processes to host the WebBrowserControl. Then, design a pipe protocol (or RMI/RPC-like) to communicate events from the main window to the child processes and vice versa.
Doing that, you can design a recycle strategy using a pool of browser processes and a background kill-and-spawn policy to get the memory consumption at a controlled level.
Have you considered using other web browser controls? There are a lot out there! I feel like chromium is a good bet, check out this question for alternatives.
I am currently doing this as follows:
// _Container is the panel that the program is to be displayed in.
System.Diagnostics.Process procTest = new System.Diagnostics.Process();
procTest.StartInfo.FileName = "TEST.EXE";
procTest.StartInfo.CreateNoWindow = false;
procTest.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
procTest.Start();
procTest.WaitForInputIdle();
SetParent(procTest.MainWindowHandle, _Container.Handle);
MoveWindow(procTest.MainWindowHandle,
0, 0, _Container.Width, _Container.Height, true);
The problem I am having with this code is that some parts of the application UI no longer function properly once I change the MainWindowHandle (ie: buttons missing text).
Is there a way to do this without causing issues with the docked application? (Either through .net or user32)?
First of all, instead of simply waiting 1.5 seconds, try calling procTest.WaitForInputIdle to wait until its message loop is free. You already are.
In general, I don't think it's possible to do this without modifying the program that you're hosting.
EDIT: You could try to keep the other program above your hosting area by hiding in from the taskbar, removing its title bar, moving it as your program moves, etc. However, this still wouldn't work perfectly; I recommend that you try to find some alternative.
Try contacting the original developers of the third-party application and asking for their advice.
I'm having trouble with something that I thought would be easy...
I can't get my NotifyIcon to show a balloon tip. The basic code is:
public void ShowSystrayBubble(string msg, int ms)
{
sysTrayIcon.Visible = true;
sysTrayIcon.ShowBalloonTip(20, "Title", "Text", ToolTipIcon.None);
}
Nothing happens when I execute this code. I read that the timeout arg may be in seconds or ms, can't tell, so I tried both and neither works.
I'm using WinXP, .NET 3.5.
I had foiled myself... This turned out to be an issue at the OS level. I had previously disabled all balloons via the registry a few weeks ago.
You can read the information here on how to disable balloon tips in WinXP:
http://support.microsoft.com/kb/307729
To enable them, just set the registry value to 1 instead and logon again/restart.
You should then log the messages for users who have disabled the balloons be able to go review them in case of need. If you can get permissions to read the registry, you could check the value and act accordingly (not to modify the value, but to log or to show the balloon).
Please see this it covers all combinations of mouse clicks with NotifyIcon as well as much more. The code is located in a template and is project setting driven so that you can implement NotifyIcon logic in all your projects with no coding effort at all.
More Here
http://code.msdn.microsoft.com/TheNotifyIconExample