|
Your logon form should be a separate but 'normal' form with labels, textboxes and buttons, as built with the designer. Then at the appropriate point in your main program you launch it by LogonForm.ShowDialog() , and you have a MFC-type modal dialog on the screen. When the user clicks the OK (or whatever) button, you just capture the inputs into your local variables, in the same way that you would in the OnOK() function in MFC. Something like:
this.Hide()
LogonForm lf = new LogonForm()
result = lf.ShowDialog();
variable = lf.textbox1;
When lf goes out of scope it will dispose itself so you do not need to.
Use the best guess
|
|
|
|
|
Thanks Richard,
that clarified some aspects of the problem. Maybe I should slightly rephrase.
As soon as I call:
result=lf.ShowDialog();
the dialog (or form) goes into some modal loop. I need to break out of that by clicking OK or Cancel. In other words, the handler code for the clicked button needs a method of breaking out of the modal loop.
N.B.Falling out of scope is a COMPILE time issue, never a RUN time issue. When execution reaches the closing scope brace, it will hit a compiler generated code block that carries out an effective cleanup and garbage collection. This would include (unlike MFC) that the Form Classes still displayed are automatically removed from the screen.
The form cannot fall out of scope while it is in the modal loop, and would remain on display forever. I used 'Dispose();' to break the circle, which on this occasion does the trick of breaking out of the loop. I am aware that this is not the proper way. For one, in doing so, lf is no longer available for interogation, and the line:
variable=lf.textbox1
would throw an exception.
In MFC I would use OnOK(), OnCancel(), or sometimes even EndDialog(nResult). How do I break out of the modal loop from within say a Button Event handler in C#.NET.
Kind regards,
Bram van Kampen
modified 16-May-13 20:34pm.
|
|
|
|
|
I think you misunderstand where the scope of the object starts and ends. The code snippet I showed you is the way to do it. When you press the OK button of your dialog, the dialog's window is no longer displayed, but the dialog object still exists, so you can extract the data from its components. For example:
void someMethod()
{
this.Hide()
LogonForm lf = new LogonForm()
result = lf.ShowDialog();
variable = lf.textbox1;
}
Use the best guess
|
|
|
|
|
I understand where the scope of an object starts and ends, I just do not know the names of the base class handlers which are (or should be) called when either the OK or Cancel button is clicked.
I used Dispose(), not because I did not understand scope, but, because it was the only method (I know it is the WRONG one) I could find that at least removed the window, and broke out of the modal loop.
I also want to find out how it is all wired up.
In de SDK we had the WindowProc, in MFC we have the MessageMap to tie events to handlers, what do we have in C#.NET? A Click on a Button event gets somewhere attached to the handler for that event. how and where?
An event handler can decide to terminate the modal loop and thereby return from ShowDialog. (how? what base method does it call to accomplish this). In other words, in MFC we have 'EndDialog' to get out of the modal loop. What do we have in C#.NET to do this?
Thanks for your time and interest,
Regards,
Update- Stop Press,
Somewhere in Stackoverflow:
"but, I know that setting DialogResult closes the form! everyone knows that!".
Well, I did not know that! One of those surprises! It would take some gymnastics in MFC to do that! At the same time, I do not think that many MFC programmers would be happy about such development.
It is where thing are organised entirely differently than what an MFC programmer in his innocence would suspect. What also does not help that everything in C#.NET has an entirely different naming convention.
Anyway, I tried it.
this.DialogResult = DialogResult.Cancel;
Closed the Dialog, and left it available for further interrogation.
The other queery stil stands. this.Hide()( called in the LogOn button handlers) hides the entire application, and not just the LogOn dialog. Is this a feature of the debug mode, or an error on my part.
Thanks again;
Bram van Kampen
modified 17-May-13 19:27pm.
|
|
|
|
|
Bram van Kampen wrote: I used Dispose(), not because I did not understand scope, but, because it was the only method (I know it is the WRONG one) I could find that at least removed the window, and broke out of the modal loop. Yes, totally wrong; you should have a button on the form that returns a DialogResult . If you click on a button on your form and look at the properties you'll see how you can set it to return OK , Cancel etc. This will then perform graceful closure of the form and return to your code.
Bram van Kampen wrote: The other queery stil stands. this.Hide()( called in the LogOn button handlers) hides the entire application, and not just the LogOn dialog. Is this a feature of the debug mode, or an error on my part. Not sure about this, I would need to run some more tests; if time allows I'll give it a try some time over the weekend.
[edit]One thing I would suggest is that you clear MFC from your mind. MFC and .NET may look similar but there are many subtle differences which can catch you out. There are plenty of beginner articles around, I found them very useful when I first started with C#.[/edit]
Use the best guess
|
|
|
|
|
I did have a bunch of similar public methods for converting an RGB structure to grey scale but decided it made the class too complicated so I changed them to private and created an Enum which was used as a parameter for a public method which then called those private methods method using switch.
One of the private methods then developed a need for a parameter, but only one of them. I made the parameter optional but then stumbled into the problem of public shared methods not being considered as constants, so I switched to overloading for this method and wanted to add an optional Enum to represent the two variants of that one method, this smelt bad. So I thought to use overloading again, but the second version of the method would still be able to accept all the options of the first Enum, even though only one was relevant, the one that needed the second Enum, still smelt bad.
I'm struggling to follow this explanation myself, so if code helps then here it is (simplified). I don't like it.
I could possibly use the second ToGreyScale method with just the LumaEnum parameter but that, to my mind, makes the use of the class problematic since it's not intuitive. Calling the second method GreyScalebyLuminosity makes a nonsense of trying to get rid of all those differently named GreyScale methods.
Is there a pattern I can use here? Or just a better design than this?
Public Overloads Sub ToGreyScale(ByVal method As RGBGreyScaleMethod)
Select Case method
Case RGBGreyScaleMethod.Average
Me.GreyScaleByAverage()
Case RGBGreyScaleMethod.BlueChannel
Me.GreyScaleFromBlue()
Case RGBGreyScaleMethod.Decompose
Me.Decompose()
Case RGBGreyScaleMethod.Luminosity
Me.GreyScaleByLuminosity()
Case Else
Throw New ArgumentOutOfRangeException()
End Select
End Sub
Public Overloads Sub ToGreyScale(ByVal method As RGBGreyScaleMethod, ByVal factors as LumaEnum)
Select Case method
Case RGBGreyScaleMethod.Luminosity
Select Case factors
Case LumaEnum.BT709
Me.GreyScaleByLuminosity(LumaFactors.BT709)
Case LumaEnum.BT601
Me.GreyScaleByLuminosity(LumaFactors.BT601)
Case LumaEnum.GIMP
Me.GreyScaleByLuminosity(LumaFactors.GIMP)
Case Else
Throw New ArgumentOutOfRangeException()
End Select
Case Else
Throw New ArgumentOutOfRangeException()
End Select
End Sub
Private Overloads Sub GreyScaleByLuminosity()
Me.GreyScaleByLuminosity(LumaFactors.BT709)
End Sub
Private Overloads Sub GreyScaleByLuminosity(ByVal factors As LumaFactors)
Dim c As Double = Me.Luminosity(factors)
Me._Red = CInt(c)
Me._Green = CInt(c)
Me._Blue = CInt(c)
End Sub
Public Enum LumaEnum
BT709
BT601
GIMP
End Enum
Public Enum
Average
BlueChannel
Decompose
Luminosity
Desaturate
Lightness
RedChannel
GreenChannel
End Enum
|
|
|
|
|
Mike-MadBadger wrote: I'm struggling to follow this explanation myself I tried twice, and got lost twice. Let's try it differently; you've seen how the different events in .NET all look similar, with two parameters? One could do something similar;
Public Class MyParamaterBase
Public Property Id As Guid
End Class
Public Class MyExtendedParameter
Public Property Title as String
End Class
Public Class SomeConsumingClass
Public Sub SomeMethod(TheParameter As MyParameterBase)
If TheParameter is MyExtendedParameter Then
Console.WriteLine((TheParameter as MyExtendedParameter).Title)
EndIf
End Sub
End Class
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Ok, so instead of an Enum parameter I have a base class parameter which through polymorphism can take a derived type which carries the extra parameter information?
I guess I could do the same thing by using an interface as the parameter?
Thanks,
Mike
|
|
|
|
|
Mike-MadBadger wrote: I guess I could do the same thing by using an interface as the parameter? Yes
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I think this is simply a variation on your suggestion (in effect), using a nested class.
Public Class Class1
Private _param As Double
Public Sub New(ByVal amount As Double)
Me._param = amount
End Sub
Public Property Param() As Double
Get
Return Me._param
End Get
Set(value As Double)
If Not value = Me._param Then
Me._param = value
End If
End Set
End Property
Public Function ToGrey() As ToGreyMethods
Return New ToGreyMethods(Me)
End Function
Public Class ToGreyMethods
Private _outer As Class1
Public Sub New(ByRef outer As Class1)
Me._outer = outer
End Sub
Public Sub Increase(ByVal amount As Double)
Me._outer.Param += amount
End Sub
Public Sub Decrease(ByVal amount As Double)
Me._outer.Param -= amount
End Sub
End Class
End Class
Module Module1
Sub Main()
Dim thing As Class1 = New Class1(10)
thing.ToGrey.Increase(5)
Console.WriteLine(thing.Param.ToString())
thing.ToGrey.Decrease(10)
Console.WriteLine(thing.Param.ToString())
Console.ReadKey()
End Sub
End Module
My only problem with this is that I can't seem to hide the nested class so one could be created at runtime manually rather than as a result of a call to ToGrey(), which starts to feel a bit messy or at least has the potential to get messy since I do.t know what would happen if, for example, you could do this.
Public Sub Example()
Dim thing as Class1 = New Class1(10)
Dim whoops as ToGreyMethods = thing.ToGrey()
End Sub
|
|
|
|
|
Mike-MadBadger wrote:
The effect would also be there without the new object; any object that's embedded in a property can be put in a variable, and one can manipulate the referenced object without looking at whose property it was.
Public Class Class1
Private _param As Double
Private _methods As ToGreyMethods
Public Sub New(ByVal amount As Double)
Me._param = amount
Me._methods = New ToGreyMethods(Me)
End Sub
Public Property Param() As Double
Get
Return Me._param
End Get
Set(ByVal value As Double)
If Not value = Me._param Then
Me._param = value
End If
End Set
End Property
Public ReadOnly Property ToGrey() As ToGreyMethods
Get
Return _methods
End Get
End Property
Public Class ToGreyMethods
Private _outer As Class1
Public Sub New(ByRef outer As Class1)
Me._outer = outer
End Sub
Public Sub Increase(ByVal amount As Double)
Me._outer.Param += amount
End Sub
Public Sub Decrease(ByVal amount As Double)
Me._outer.Param -= amount
End Sub
End Class
End Class
Module Module1
Sub Main()
Dim thing As Class1 = New Class1(10)
thing.ToGrey.Increase(5)
Console.WriteLine(thing.Param.ToString())
thing.ToGrey.Decrease(10)
Console.WriteLine(thing.Param.ToString())
Dim whoops As Class1.ToGreyMethods = thing.ToGrey()
Console.ReadKey()
End Sub
End Module
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
BTW, I'd give a +5 but there's no option to do so
|
|
|
|
|
<- It's hidden
|
|
|
|
|
Use a definition object. That is passed to the second object and defines how it runs. The definition object can provide things like a default definition, common definitions, common ways to create definitions and custom definitions.
|
|
|
|
|
Unfortunately I'm not sure exactly what a definition object is and Google hasn't helped, could you possibly help me with a link or a bit more explanation?
|
|
|
|
|
pseudo code
pre>
Object Def
ByVal method As RGBGreyScaleMethod;
ByVal factors as LumaEnum;
...
Object Implem
Doit(Def def)
|
|
|
|
|
It looks like you found a solution that you are happy with, but I thought that I would throw my 2 cents worth into the fray.
Based on my understanding of your code, the Luminosity method is the only one that needs a second parameter. Why not remove Luminosity from your methods enum and change:
Public Overloads Sub ToGreyScale(ByVal method As RGBGreyScaleMethod, ByVal factors as LumaEnum)
to:
Public Overloads Sub ToGreyScale(ByVal factors as LumaEnum)
I think that this would given you the intuitiveness factor that you are seeking.
As I don't know what it all is that you are doing in this "Class" the following may not be relevant, but I will throw it out as an alternative. It appears that all you are using it for is to convert a Color structure to its equivalent greyscale color. Perhaps, this may be a case for using extension methods to the Color Structure.
Module GreyScaleExtentions
Public Enum RBGMethods
Average
BlueChannel
Decompose
Desaturate
Lightness
RedChannel
GreenChannel
End Enum
Public Enum LumaEnum
BT709
BT601
GIMP
End Enum
''' <summary>
''' Converts Color to greyscale equivalent using RGBGreyScaleMethod
''' </summary>
''' <param name="c"></param>
''' <param name="RGBMethod"></param>
''' <returns></returns>
''' <remarks></remarks>
<Runtime.CompilerServices.Extension()> _
Public Function ToGreyScale(ByVal c As Color, ByVal RGBMethod As RBGMethods) As Color
End Function
''' <summary>
''' Converts Color to greyscale equivalent using luminosity method
''' </summary>
''' <param name="c"></param>
''' <param name="factors"></param>
''' <returns></returns>
''' <remarks></remarks>
<Runtime.CompilerServices.Extension()> _
Public Function ToGreyScale(ByVal c As Color, ByVal factors As LumaEnum) As Color
End Function
End Module
Then you could use like this:
Sub test()
Dim c As Color = Color.FromArgb(230, 134, 231, 10)
Dim gs As Color
gs = c.ToGreyScale(LumaEnum.BT601)
gs = c.ToGreyScale(RBGMethods.Average)
End Sub
|
|
|
|
|
That one had occured but it meant that a user of the class would need to know that the overload without a method would give ByLuminosity, which was the bit that felt unintuitive.
BTW, thanks for the <Runtime.CompilerServices.Extension()> piece, I assume that's how extension methods work?
I might add those to extend the Color type to include the functionality in my RGB and aRGB types, thanks.
|
|
|
|
|
Quote: That one had occured but it meant that a user of the class would need to know that the overload without a method would give ByLuminosity, which was the bit that felt unintuitive.
The issue of being intuitive is very subjective. I see the intuitive part being to use the "ToGreyScale" method and even that may require some explanation. At some point a programmer has to demonstrate some competence and look at the provided documentation. This is the reason that I showed the visual studio intellisense support using xml comments in the code I posted (see: Documenting Your Code With XML Comments). Providing this documentation is your responsibility as the developer and you should not be relying on something being intuitive as a substitute for proper documentation. Paste the extension method code I provided into a project and observe the intellisence pop-ups when you try to use the defined methods.
Quote: BTW, thanks for the piece, I assume that's how extension methods work?
Assume nothing when coding. Use your friendly search engine and research it yourself. I have found that this general query works well in the major search engines:
msdn TopicYouWant -social"
The reason for the "-social" is to try to eliminate results from the msdn help forums and to focus on the documentation pages.
So much for my preaching for the day, have a good weekend.
|
|
|
|
|
Thank you. My code is XML commented I just left it out of the simplified examples here. For the extension methods I'm not sure why I left the question in, I had searched Google, guess I was just looking for confirmation - probably not necessary.
On the structure, I agree but something feels clunky, nevermind.
Have a nice weekend
|
|
|
|
|
I have an DLL assembly that is used by many other apps. This assembly is likely to change as new requirements are discovered.
Now, let's say the referencing apps are all running, I change the code in the dll for a new app, and then start the new app.
What I'm seeing is that the new app uses the version of the assembly that's already in memory. Is that an accurate statement?
If so, is there a way to force the new app to use the copy of the dll that it was linked to instead of using what's already in memory?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997
|
|
|
|
|
The running application (or new application using currently cached DLL) doesn't know about changes to the DLL itself in most cases, so you'd have to write some kind of polling thing, or event response to the Windows file changed event, and pick up the new DLL and link it in "manually" like this...
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");
Type type = assembly.GetType("MyType");
object instanceOfMyType = Activator.CreateInstance(type);
This is frustrating for sure, when you have lots of apps using the same DLLs - I've had this issue with multiple web sites before, and it took us a long time to understand what was happening. You would think that copying over the old DLL would cause a system-wide "this DLL is no longer up to date" kind of event, but apparently not.
|
|
|
|
|
I tried using strong naming, but that had no effect.
WTF good is code re-use if I can't actually re-use the freakin code in compiled form?
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997
|
|
|
|
|
Yeah it's not ideal. Sometimes you have to re-start the server. I think they opted for making it harder to use the wrong assembly instead of easier to manipulate which ones are used.
|
|
|
|
|
John Simmons / outlaw programmer wrote: ...by many other apps.
What do you mean by "app"? Or more specifically how many process spaces are you running into which these apps appear?
An executable/service has a load dynamic that, excluding GAC, will load based on several factors but the primary one is the current working directory of the primary executable. A new process space will load a new copy of the dll that it found doing an assembly search. It doesn't have anything to do with what other processes have loaded into memory.
Now if you are messing with AppDomains and changing the loading semantics then that alters how it searches and that would alter where it looked. The process would still load a new copy though.
John Simmons / outlaw programmer wrote: What I'm seeing is that the new app uses the version of the assembly that's
already in memory. Is that an accurate statement?
Not in general, but as noted it depends on what you mean by "app". The process (AppDomain) loads the dll into memory. It won't load it again, but every process gets one (I can't remember if there is AppDomain chaining or not.)
|
|
|
|
|