The Sharp6502 IDE continues to take shape - I've been chugging along writing WinForms code for the last couple of days, getting things like standard menu-handling and form control logic in place. It's all been pretty straight-forward, aside from one little glitch that had me stumped for a while.
The scenario is this: we want a nice, clean, efficient bit of code that can be called by any menu item (on the main MDI form) that needs to open a child window. By passing such a method an identifier, the menu Click event can tell it which of a variety of child windows it is asking to be opened. Thus, by making the identifier a string in the menu item Tag field, the exact same window-opening code can be called by any menu item; the actual window that opens will be whichever one the identifier indicated. There's probably a better way of doing this, but it's a technique that's reasonably easy to understand and maintain, and has served me well for the last decade or so.
Anyway, in some cases we might not want to open a window if one already exists - a lot of the child windows can be open multiple times, but just occasionally we want a single instance of a particular one. So the window-open code has a loop to scan through the extant child windows, and it makes a note if an instance of the window it's being asked to open is already present. Then when we come to actually create and show the window, for those that must be single-instance we check the flag to see if there already is one, and just activate it if there is (or create it if there isn't).
To figure-out if a window is already present, we simply compare the names of all the forms in the MDIChildren collection with the identifier the menu item gave us - those identifiers are just the form name the menu item wants to open, so we can very easily tell if there's already one in existence. And it's this little test that had me scratching my head for a good half-an-hour last night, because although it worked for most of the windows, there was one it just would not play ball with - I never managed to get a match on name, so even though I only wanted a single instance, I always got another window opened. Highly confusing, and not a little irritating.
I carefully checked that the form name I had stashed as an identifier in the menu item Tag was right - it was. I checked that the identifier made it through to the instance-checking code intact and unmangled in some peculiar way - it did. I made sure that the comparison was checking Form.Name against the identifier - it was. I looked at what was in Form.Name in the cases where it worked - it matched. I looked at the contents of Form.Name in the case where it didn't work - and it didn't match! WTF?
Somehow, the form name (which should have been reported as 'frmXXX') was actually coming back as just 'XXX'. So my identifier, containing 'frmXXX', didn't match, and the application then went on and created a new window. How the hell was my forms' name getting broken?
Well, I checked every damn thing I could see, and played around with the code for a quarter of an hour or so, before getting to that 'grasping at straws' stage when, having eliminated the impossible, whatever remains (however improbable) must be the cause. The only difference between the 'problem' form and the ones that worked was that it had a different border style. The others are all the usual 'Sizable' type, but this one is 'FixedToolWindow', because it's a little helper-utility that exists as a single instance. And unbelievably, when I changed it to have a 'Sizable' border, the Form.Name came back as 'frmXXX'.
So for some arcane reason (and there must be a reason, surely?) the WinForms engine chops the 'frm' prefix off the form name if it's got a 'FixedToolWindow' border style. I haven't tried this with other prefixes, because I need to press on - but if anyone out there knows what the cause of this behavior is, I'd be very interested to know. And yes, I know the use of Hungarian Notation for objects is now frowned-upon and I shouldn't be using 'frm' anyway - but until the Visual Studio Solution Explorer has a way of grouping objects so that my forms and other stuff are separated-out from each other and I can readily see which things are forms, and which are standard classes, I'm going to keep on defying convention.
Anyway, another few days should have the IDE running with a Disassembler view, so I'll post a screenshot or two at that point. Stay tuned!
EDIT: Just after I posted this, I re-ran the code and it looks like the naming glitch might actually have been caused by something else; when I switched the problem form back to 'FixedToolWindow', it still reports it's name as 'frmXXX' - so something got broken deep in the form engine system somewhere, and changing the border style fixed it. It's still wierd, but evidently not a fundamental problem. Hey ho.
The scenario is this: we want a nice, clean, efficient bit of code that can be called by any menu item (on the main MDI form) that needs to open a child window. By passing such a method an identifier, the menu Click event can tell it which of a variety of child windows it is asking to be opened. Thus, by making the identifier a string in the menu item Tag field, the exact same window-opening code can be called by any menu item; the actual window that opens will be whichever one the identifier indicated. There's probably a better way of doing this, but it's a technique that's reasonably easy to understand and maintain, and has served me well for the last decade or so.
Anyway, in some cases we might not want to open a window if one already exists - a lot of the child windows can be open multiple times, but just occasionally we want a single instance of a particular one. So the window-open code has a loop to scan through the extant child windows, and it makes a note if an instance of the window it's being asked to open is already present. Then when we come to actually create and show the window, for those that must be single-instance we check the flag to see if there already is one, and just activate it if there is (or create it if there isn't).
To figure-out if a window is already present, we simply compare the names of all the forms in the MDIChildren collection with the identifier the menu item gave us - those identifiers are just the form name the menu item wants to open, so we can very easily tell if there's already one in existence. And it's this little test that had me scratching my head for a good half-an-hour last night, because although it worked for most of the windows, there was one it just would not play ball with - I never managed to get a match on name, so even though I only wanted a single instance, I always got another window opened. Highly confusing, and not a little irritating.
I carefully checked that the form name I had stashed as an identifier in the menu item Tag was right - it was. I checked that the identifier made it through to the instance-checking code intact and unmangled in some peculiar way - it did. I made sure that the comparison was checking Form.Name against the identifier - it was. I looked at what was in Form.Name in the cases where it worked - it matched. I looked at the contents of Form.Name in the case where it didn't work - and it didn't match! WTF?
Somehow, the form name (which should have been reported as 'frmXXX') was actually coming back as just 'XXX'. So my identifier, containing 'frmXXX', didn't match, and the application then went on and created a new window. How the hell was my forms' name getting broken?
Well, I checked every damn thing I could see, and played around with the code for a quarter of an hour or so, before getting to that 'grasping at straws' stage when, having eliminated the impossible, whatever remains (however improbable) must be the cause. The only difference between the 'problem' form and the ones that worked was that it had a different border style. The others are all the usual 'Sizable' type, but this one is 'FixedToolWindow', because it's a little helper-utility that exists as a single instance. And unbelievably, when I changed it to have a 'Sizable' border, the Form.Name came back as 'frmXXX'.
So for some arcane reason (and there must be a reason, surely?) the WinForms engine chops the 'frm' prefix off the form name if it's got a 'FixedToolWindow' border style. I haven't tried this with other prefixes, because I need to press on - but if anyone out there knows what the cause of this behavior is, I'd be very interested to know. And yes, I know the use of Hungarian Notation for objects is now frowned-upon and I shouldn't be using 'frm' anyway - but until the Visual Studio Solution Explorer has a way of grouping objects so that my forms and other stuff are separated-out from each other and I can readily see which things are forms, and which are standard classes, I'm going to keep on defying convention.
Anyway, another few days should have the IDE running with a Disassembler view, so I'll post a screenshot or two at that point. Stay tuned!
EDIT: Just after I posted this, I re-ran the code and it looks like the naming glitch might actually have been caused by something else; when I switched the problem form back to 'FixedToolWindow', it still reports it's name as 'frmXXX' - so something got broken deep in the form engine system somewhere, and changing the border style fixed it. It's still wierd, but evidently not a fundamental problem. Hey ho.

0 comments:
Post a Comment