is there way to make the default messagebox ( MessageBox.Show() ) TopMost true which also stays on top even if the messagebox lost the focus?
I don't want to create a custom one.
Is there a way doing it by using SetWindowHook or something similar?
I already researched a lot but all solutions I found were not working.
Can someone help me out how to do this in VB.net or C#?
The simplest way is to p/invoke the MessageBox function and pass the MB_SYSTEMMODAL flag.
I got it.
This will show a messagebox on top of all windows opened, doesn't matter if they have Topmost options or not, the messagebox appears always in front.
Public Enum MessageBoxResult As UInteger
Ok = 1
Cancel
Abort
Retry
Ignore
Yes
No
Close
Help
TryAgain
ContinueOn
Timeout = 32000
End Enum
Public Enum MessageBoxOptions As UInteger
SystemModal = &H1000
NoFocus = &H8000
SetForeground = &H10000
Topmost = &H40000
End Enum
<DllImport("user32.dll", EntryPoint:="MessageBoxW", SetLastError:=True, Charset:=CharSet.Unicode)> _
Public Shared Function MessageBox(hwnd As IntPtr, _
<MarshalAs(UnmanagedType.LPTStr)> lpText As String, _
<MarshalAs(UnmanagedType.LPTStr)> lpCaption As String, _
<MarshalAs(UnmanagedType.U4)> uType As MessageBoxOptions) As <MarshalAs(UnmanagedType.U4)> MessageBoxResult
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox(IntPtr.Zero, TextBox2.Text, TextBox1.Text, MessageBoxButtons.OK Or MessageBoxOptions.SystemModal + MessageBoxOptions.Topmost + MessageBoxOptions.SetForeground + MessageBoxIcon.Information)
End Sub
End Class
Related
Actually I wanted to use cefsharp with my VB6 project and I am having following two problems:-
My project runs from let's say form1 and I need to call form2 where I have initialized the chromium browser using cefsharp by making use of C# class library.
Now when I call form2 from form1 like
form2.showme
(Where showme is just a custom function to set size etc) the chromium browser is able to get initialized without any issues, but when I call form2 like
Public ofrm2 AS form2
Public Sub function()
Set ofrm2=new form2
call ofrm2.showme
End Sub
then even though no error log or error of any kind is given and form2 is shown successfully, but there is no cefsharp chromium browser object on it this time.
I am also using SetParent and SetWindowPos to set up the length and width of my chromium browser in form2. I really am unable to find the issue, please suggest some fix.
The second problem is VB6 Editor does not allow debugging as soon as my code Initializes chromium. The only way to test the application for me was to make an exe and then run the application and try debugging using logs.
Edit:- ****************************************************************
My C# dll containing cefsharp packages
[PermissionSet(SecurityAction.Demand, Name ="FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
[ClassInterface(ClassInterfaceType.None)]
public partial class Form1 : Form, IForm1
{
private ChromiumWebBrowser _browser;
public Form1()
{
InitializeComponent();
//initializeChromium();
}
public int initializeChromium()
{
CefSettings settings = new CefSettings();
if (!Cef.IsInitialized)
{
CefSharp.Cef.Initialize(settings);
}
_browser = new ChromiumWebBrowser("http://127.0.0.1:24125/ABC/DEF.html");
_browser.RegisterJsObject("External", this);
this.Controls.Add(_browser);
_browser.BringToFront();
_browser.Dock = DockStyle.Fill;
this.Show();
return 0;
}
}
My Form1:-
Private Sub Form_Load()
Call launch ------ This one does not work. definition is given in my module below
'frmHTML.Show -----This one works
End Sub
Private Sub Form_UnLoad(cancel As Integer)
Set ofrmHtml = Nothing
End Sub
ModDec.bas:-
Option Explicit
Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Public Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Public ofrmHtml As frmHTML
Public Sub launch()
Set ofrmHtml = New frmHTML
Call ofrmHtml.InitChromium1
ofrmHtml.ShowMe
'call ofrmHtml.ShowMe
End Sub
My form2(frmHTML):-
Option Explicit
Public cSharpObj As New cSharp.Form1
Private Sub Form_Load()
'Call InitChromium1
Exit Sub
End Sub
Public Sub InitChromium1()
' On Error GoTo Err_Hndlr
SetParent cSharpObj.getHandle, frmHTML.hWnd
SetWindowPos cSharpObj.getHandle, 0, 0, 0, 512, 480, 0
Dim i As Integer
i = -1
i = cSharpObj.initializeChromium()
Exit Sub
End Sub
Public Sub ShowMe()
Call Me.Show
End Sub
I've got an app using .net UIAutomation, it eventually runs out of memory and crashes just monitoring windows being shown and closed. Seemed easier to show this in VB than C# but happens the same either way. It appears to be a leak/pool in the underlying proxy objects. Most of the memory is not being shown as in use as .net memory.
Any ideas on how to get this to stop leaking and still monitor StructureChangedEvents?
Imports System.Windows.Automation
Public Class Form1
Delegate Sub AddListCallback(ByVal Text As String)
Dim UIAeventHandler As StructureChangedEventHandler
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
BtnStartStop.Text = "Stop"
Subscribe()
End Sub
Private Sub BtnStartStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStartStop.Click
If "Start" = BtnStartStop.Text Then
BtnStartStop.Text = "Stop"
Subscribe()
Else
BtnStartStop.Text = "Start"
Unsubscribe()
lbEvents.Items.Clear()
GC.GetTotalMemory(True)
End If
End Sub
Public Sub Subscribe()
UIAeventHandler = New StructureChangedEventHandler(AddressOf OnUIAutomationEvent)
Automation.AddStructureChangedEventHandler(AutomationElement.RootElement, TreeScope.Descendants, UIAeventHandler)
End Sub
Public Sub Unsubscribe()
Automation.RemoveStructureChangedEventHandler(AutomationElement.RootElement, UIAeventHandler)
End Sub
''' <summary>
''' AutomationEventHandler delegate.
''' </summary>
''' <param name="src">Object that raised the event.</param>
''' <param name="e">Event arguments.</param>
Private Sub OnUIAutomationEvent(ByVal src As Object, ByVal e As StructureChangedEventArgs)
' Make sure the element still exists. Elements such as tooltips can disappear
' before the event is processed.
If e.StructureChangeType = StructureChangeType.ChildrenInvalidated Then
Exit Sub
End If
Dim sourceElement As AutomationElement
Try
sourceElement = DirectCast(src, AutomationElement)
Catch ex As ElementNotAvailableException
Exit Sub
End Try
' TODO Handle any other events that have been subscribed to.
Console.WriteLine( "Element : """ & sourceElement.Current.LocalizedControlType & """ """ & sourceElement.Current.Name _
& """ Struct Change Type : " & [Enum].GetName(GetType(StructureChangeType), e.StructureChangeType) _
& " Runtime ID : " & getString(e.GetRuntimeId()))
End Sub
Private Function getString(ByVal ints As Integer()) As String
getString = ""
For Each i As Integer In ints
getString = getString & " " & i.ToString
Next
End Function
End Class
I would do something like this when you unsubscribe:
Automation.RemoveAllEventHandlers();
UIAeventHandler = null;
UIAutomation will keep some threads alive as long as you've got an AutomationEventHandler object around. Its pretty much a black box to me, but the above has fixed all issues that I had.
#jaws is correct (there are some additional things to think about), but it is in C#. for VB you need to do the following:
Automation.RemoveStructureChangedEventHandler(AutomationElement.RootElement, UIAeventHandler)
UIAeventHandler = Nothing
Because you do not set the UIAeventHandler to nothing, when you unsubscribe then, you are re-assigning the event handler which is already in memory.
To think about. Notice that you are calling subscribe when the form loads and subscribe/unsubscribe with a button. When the form loads then, the event handler is assigned and should work fine, that is until you hit unsubscribe/subscribe (in that order). When you did not set the UIAeventHandler to Nothing then, you are causing a memory leak because you then set the UIAeventHandler to a NEW instance on subscribe. Therefore, you could also do the following as suggested by #jaws :
Imports System.Windows.Automation
Public Class Form1
Dim UIAeventHandler as StructureChangedEventHandler
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
BtnStartStop.Text = "Stop"
Subscribe()
End Sub
Public Sub Subscribe()
UIAeventHandler = New StructureChangedEventHandler(AddressOf OnUIAutomationEvent)
Automation.AddStructureChangedEventHandler(AutomationElement.RootElement, TreeScope.Descendants, UIAeventHandler)
End Sub
Public Sub Unsubscribe()
Automation.RemoveStructureChangedEventHandler(AutomationElement.RootElement, UIAeventHandler)
UIAeventHandler = Nothing 'Here is the Important part!
End Sub
End Class
I am using Bass. I would like to set a callback so when the song reaches to end i can play another song directly after.
Its not C#, but here's some VB.Net code you should be able to convert easily enough:
Set up the callback
' Mixer handle to the bass synch callback when the current track in the mixer ends
Private m_MixerSynchProc As Un4seen.Bass.SYNCPROC
Private m_MixerSyncHandle As Int32 = 0
' Create a new callback for when the current track in the mixer has ended
m_MixerSynchProc = New Un4seen.Bass.SYNCPROC(AddressOf CurrentTrackEnded)
m_MixerSyncHandle = Bass.BASS_ChannelSetSync(m_MixerHandle, Un4seen.Bass.BASSSync.BASS_SYNC_END Or Un4seen.Bass.BASSSync.BASS_SYNC_MIXTIME, 0, m_MixerSynchProc, 0)
A delegate sub that BASS will call when the track is ended
' Mixer sync proc callback for when the current track has ended
Private Sub CurrentTrackEnded(ByVal MixerHandle As Int32, ByVal Channel As Int32, ByVal Data As Int32, ByVal User As IntPtr)
' Do stuff here when the track ends
End Sub
After finding this question and following the instructions there, plus following many of the links, I managed to get my app to appear as a system tray icon, and it disappears from the task bar when I minimize it.
BUT - weird behavior! When the form is open, the system tray icon works fine. But as soon as I minimize it, the tray icon stops responding to any kind of mouse click.
Other facts that may come into play: the form is started up by a thread spun off from the main thread, and it is opened with .ShowDialog(). There are also several other threads running in the background.
Any ideas what's going wrong?
Replace f.ShowDialog(); with Application.Run(f); where f is the variable holding your Form and it should work fine. The problem is that ShowDialog returns (and it's message loop ends) when you hide the form. Application.Run provides a proper message loop and your window works after it has been hidden and can be show again using the system tray icon.
Not too sure what your code looks like, but below is some code I pulled from one of our apps. Its written in VB but should not be too hard for you to convert. The key is to create an ApplicationContext class to host your code. This code has no problems showing a form and then closing it repeatedly or with minimizing or maximizing.
Public Class NotifyApplicationContext
Inherits ApplicationContext
Private components As System.ComponentModel.IContainer
Private Notify As System.Windows.Forms.NotifyIcon
Private Menu As System.Windows.Forms.ContextMenu
Private mnuForm As System.Windows.Forms.MenuItem
Private F As Form
Public Sub New()
InitializeContext()
End Sub
Private Sub InitializeContext()
Me.components = New System.ComponentModel.Container
Me.Notify = New System.Windows.Forms.NotifyIcon(Me.components)
SetupContextMenu()
Notify.ContextMenu = Me.Menu
Notify.Icon = New Icon("YourApplicationIcon", 16, 16)
Notify.Text = "Your Application Text"
Notify.Visible = True
F = New Form
F.Show()
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
MyBase.Dispose(disposing)
End Sub
Protected Overrides Sub ExitThreadCore()
MyBase.ExitThreadCore()
End Sub
Private Sub SetupContextMenu()
Me.Menu = New System.Windows.Forms.ContextMenu
Me.mnuForm = New System.Windows.Forms.MenuItem
Me.Menu.MenuItems.Add(mnuForm)
mnuForm.Index = 7
mnuForm.Text = "FormText"
AddHandler mnuForm.Click, AddressOf Me.mnuTemp_Click
End Sub
Private Sub mnuForm_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If F IsNot Nothing Then
If F.Visible = True Then
F.Close()
F.Dispose()
F = Nothing
End If
Else
F = New Form
F.Show()
End If
Notify.Text = "Change Application Text Here"
End Sub
End Class
Public Class Startup
<STAThread()> _
Public Shared Sub Main()
Dim N As ApplicationContext = New NotifyApplicationContext
Application.Run(N)
End Sub
End Class
Is it possible to show/hide the scroll bar in a text box only when the line count in the text box is more than the number of lines displayed?
Consider using the RichTextBox -- it has that behavior built in.
Thanks dummy, it works! Here short version of dummy answer in c#
Call this code at the end of your SizeChanged and TextChanged handlers:
Size textBoxRect = TextRenderer.MeasureText(
this.YourTextBox.Text,
this.YourTextBox.Font,
new Size(this.YourTextBox.Width, int.MaxValue),
TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl);
try
{
this.YourTextBox.ScrollBars = textBoxRect.Height > this.YourTextBox.Height ?
ScrollBars.Vertical :
ScrollBars.None;
} catch (System.ComponentModel.Win32Exception)
{
// this sometimes throws a "failure to create window handle" error.
// This might happen if the TextBox is unvisible and/or
// too small to display a toolbar.
}
Public Class TextBoxScrollbarPlugin
Private WithEvents mTarget As TextBox
''' <summary>
''' After the Handle is created, mTarget.IsHandleCreated always returns
''' TRUE, even after HandleDestroyed is fired.
''' </summary>
''' <remarks></remarks>
Private mIsHandleCreated As Boolean = False
Public Sub New(item As TextBox)
mTarget = item
mIsHandleCreated = mTarget.IsHandleCreated
End Sub
Private Sub Update()
If Not mTarget.IsHandleCreated Then
Return
ElseIf Not mIsHandleCreated Then
Return
End If
Dim textBoxRect = TextRenderer.MeasureText(mTarget.Text,
mTarget.Font,
New Size(mTarget.Width, Integer.MaxValue),
TextFormatFlags.WordBreak + TextFormatFlags.TextBoxControl)
Try
If textBoxRect.Height > mTarget.Height Then
mTarget.ScrollBars = ScrollBars.Vertical
Else
mTarget.ScrollBars = ScrollBars.None
End If
Catch ex As System.ComponentModel.Win32Exception
'this sometimes throws a "failure to create window handle"
'error.
'This might happen if the TextBox is unvisible and/or
'to small to display a toolbar.
If mLog.IsWarnEnabled Then mLog.Warn("Update()", ex)
End Try
End Sub
Private Sub mTarget_HandleCreated(sender As Object, e As System.EventArgs) Handles mTarget.HandleCreated
mIsHandleCreated = True
End Sub
Private Sub mTarget_HandleDestroyed(sender As Object, e As System.EventArgs) Handles mTarget.HandleDestroyed
mIsHandleCreated = False
End Sub
Private Sub mTarget_SizeChanged(sender As Object, e As System.EventArgs) Handles mTarget.SizeChanged
Update()
End Sub
Private Sub mTarget_TextChanged(sender As Object, e As System.EventArgs) Handles mTarget.TextChanged
Update()
End Sub
End Class
Private mPlugins As New List(Of Object)
Private Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
mPlugins.Add(New TextBoxScrollbarPlugin(txtBoxOne))
mPlugins.Add(New TextBoxScrollbarPlugin(txtBoxTwo))
mPlugins.Add(New TextBoxScrollbarPlugin(txtBoxThree))
End Sub
I've got tnimas solution working in vb. Functions quite well as written and I've not seen the errors.
Private Sub TextBoxSizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
Dim textBoxRect As Size = TextRenderer.MeasureText(TextBox.Text, TextBox.Font, New Size(TextBox.Width, Integer.MaxValue), TextFormatFlags.WordBreak Or TextFormatFlags.TextBoxControl)
Try
TextBox.ScrollBar = If(textBoxRect.Height > TextBox.Height, ScrollBars.Vertical, ScrollBars.None)
Catch ex As Exception
'handle error
End Try
End Sub
I myself tried tnimas' solution but unable to catch the exception, so I use the WinApi to toggle the visible state of scrollbars instead like so:
Size textBoxRect = TextRenderer.MeasureText(YourTextBox.Text, YourTextBox.Font, new Size(YourTextBox.Width, int.MaxValue), TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl);
WinApi.ShowScrollBar(YourTextBox.Handle, (int)WinApi.ScrollBar.SB_VERT, textBoxRect.Height > YourTextBox.Height ? true : false);
This method does not cause the exception, though should note that hiding scrollbars like this will disable scroll messages, but this is fine if you're just hiding the scrollbars for when the text area can't be scrolled anyway.