9 ms·
Building Win16 GUI Applications in C (2014)
- keithnz 10y agobeen there, done that, never going back! :) it was fun at the time, though information was limited and precious, you ended up being very dependent on books and magazines to find out about how to get things done.
- bitwize 10y agoBooks, magazines, abd CompuServe! PC Magazine had Win16 experts answering questions on CompuServe.
- Maarten88 10y agoCrazy times. A null pointer reference used to cause a full computer reboot. You had to read your printf logs to find where approximately the program stopped. I spent a sizeable amount of my scholarship money on Microsoft Systems Journals, Charles Petzolds "Programming Windows" and "Undocumented Windows". The latter would teach you tricks like saving the Window position in an INI file so you could make it reappear in the same place where it was closed...
- bhdz 10y agoIt was very funny making Dialogs with a randomly moving "OK" button responding on WM_MOUSEOVER (or something like it). Make them bigger, toolboxes, always on-top, and disable the top-right "x" button. Fun times :P
- userbinator 10y agoOn discovering that buttons and other controls were just different classes of windows, I wrote a few little games that took advantage of it to spawn moving buttons, checkboxes, and other widgets. Their sources and binaries are probably still somewhere, but not currently on this computer. Incidentally, I believe Minesweeper also does the same with its grid --- they're just buttons.
- pryelluw 10y agoWorse was when those resources were not available. You were pretty much SOL.
- userbinator 10y agoSome more interesting articles on the MakeProcInstance mechanism: https://blogs.msdn.microsoft.com/oldnewthing/20080207-00/?p=23533 https://blogs.msdn.microsoft.com/oldnewthing/20080207-00/?p=... http://www.geary.com/fixds.html http://www.geary.com/fixds.html ...and if you think the 16-bit segmented architecture is annoying, you probably haven't worked with a bank-switched 8-bit system. ;-)
- Stratoscope 10y agoThanks for the mention! Creating FixDS was definitely one of those "aha!" moments for me. Like every other Windows programmer of that era, I just assumed that all the rigmarole with EXPORTS and MakeProcInstance() was necessary. It was simply How Things Are Done. So seeing that EXPORTS and MakeProcInstance() existed solely for the purpose of loading the DS register, and finding that in application code the correct value was already in the SS register and could simply be copied over into DS? That was quite a surprise. Why were we all going to so much work when it wasn't necessary at all? Ever since then, I've had my eye out for places where the conventional wisdom tells us to write code we don't need. One that I've seen a lot lately - especially in StackOverflow answers - is an unnecessarily complicated way of creating closures in JavaScript. Many JavaScript programmers seem to believe that the way you create a closure is by writing a function that returns a function. That works, of course, but unless you really need a function that returns a function, it's a complication you can do without. After all, a simple function call can create a closure all by itself. For example, someone is writing a Google Maps API app that takes an array of data about different places, loops through the array with a for loop, and creates a marker for each of those places along with a click event handler for each marker. Experienced JavaScript programmers can probably guess what the problem is going to be. I'll simplify the code a bit here to illustrate: var places = [ { name: "One", lat: 34.1, lng: -80.7 }, { name: "Two", lat: 35.2, lng: -81.8 } ]; var infowindow = new google.maps.InfoWindow(); for( var i = 0; i < places.length; i++ ) { var marker = new google.maps.Marker({ position: new google.maps.LatLng( places[i].lat, places[i].lng ), map: map }); google.maps.event.addListener( marker, 'click', function() { infowindow.setContent( places[i].name ); infowindow.open( map, marker ); }); } The problem here, of course, is that when the click callback function is called asynchronously, the for loop has already run to completion, and the i and marker variables no longer have the correct values for the marker that was clicked. Inevitably, someone will now answer this question by suggesting a closure, and illustrating how you get a closure by using a function that returns a function: for( var i = 0; i < places.length; i++ ) { var marker = new google.maps.Marker({ position: new google.maps.LatLng( places[i].lat, places[i].lng ), map: map }); // Changes are below, using a function that returns a function google.maps.event.addListener( marker, 'click', (function( marker, i ) { return function() { infowindow.setContent( places[i].name ); infowindow.open( map, marker ); } })( marker, i ); } While that works, it's harder to understand than it needs to be. It's like using EXPORTS and MakeProcInstance() to load the DS register. There is a simpler way: for( var i = 0; i < places.length; i++ ) { addMarker( places[i] ); } function addMarker( place ) { var marker = new google.maps.Marker({ position: new google.maps.LatLng( place.lat, place.lng ), map: map }); google.maps.event.addListener( marker, 'click', function() { infowindow.setContent( place.name ); infowindow.open( map, marker ); }); } By simply calling a function in the loop, we create the closure we need, and we get simpler and more readable code too. Of course you can achieve the same effect by using array.forEach(), because that calls a function and gives you a closure automatically: places.forEach( function( place ) { var marker = new google.maps.Marker({ position: new google.maps.LatLng( place.lat, place.lng ), map: map }); google.maps.event.addListener( marker, 'click', function() { infowindow.setContent( place.name ); infowindow.open( map, marker ); }); }); Here's a search that will show numerous StackOverflow answers that promote the complicated function-returning-a-function pattern: https://www.google.com/search?q=stackoverflow+maps+api+marker+closure+function+returns+function https://www.google.com/search?q=stackoverflow+maps+api+marke...
- deleted 10y ago[deleted]
- _RPM 10y agoThat's pretty cool that the executable will run on Windows 10 today. I have respect for Windows, but that is really impressive.
- digi_owl 10y agoWhile i sit here watching gvfs shit itself randomly because of a minor glib version bump. This kind of crap is why there is still no "year of the desktop".
- vbezhenar 10y agoWinAPI and glib are different things. Compare WinAPI to libc API and Xlib. And I'm sure, you can run X application from 1990 on current Linux. I've learned X programming in 2005, and many resources and mans were dated 1990-1995. They all worked. Though OpenSource often tends to move forward without thinking much about compatibility, that's right. I guess, it's not an interesting topic for hackers, who work in their free time.
- rincebrain 10y agoYou'd certainly need to go through a _lot_ of hoops to make it run - a number of X extensions have come and gone, and even assuming you're not consuming some additional library and are just writing X calls... ...Linux 0.01 didn't come out until 1991, so you'd be hard-pressed to find a compatible binary from 1990. ;)
- david-given 10y agoIt's an interesting exercise to pull up an old (but reasonably complex) Xlib app and run it on a modern machine; xfig, for example. They never pause for breath. Like, you cannot see the application think. Ever. Whenever you ask it to do something, it responds instantly. You click the mouse, and by the next frame the app has updated and is waiting for your instructions. It's astonishing how much nicer this makes them to use. (And it's interesting that the Xaw classic design is... um... well, it's as ugly as hell, but it's a kind of functional ugliness which you stop seeing after a bit. Motif, on the other hand, remains awful. The really interesting one of the old widget sets is Open Look, which still looks elegant and polished today: http://www.daylight.com/dayhtml/doc/thor/thor.sample3.gif http://www.daylight.com/dayhtml/doc/thor/thor.sample3.gif) I wonder if there's any mileage in resurrecting one of these old widget systems? Update it to work with modern languages and desktop environments, make sure the accessibility's up to scratch (Motif got this right; don't know about Xaw and Open Look), make sure that modern workflow menus-and-windows apps can be written using them...
- pistle 10y agoAhhh... the days... I remember fumbling through something very similar to this and the time I spent in MainWndProc once the application became significantly complex could be awfully frightening for a noob like me.
- bhdz 10y agoI "invented" a dispatcher library back then for that. Marking and matching callbacks with strings and looping through in the proc [ was very proud with it :-) ]
- lnternet 10y agoHeh, I always thought of Win16 as the Windows 3.x API. It never occurred to me that the "same" API was used for Windows 2.x and even 1.x. Makes sense though... Really cool to see that Windows 1.0 application run on Windows 10!
- pavlov 10y agoWith some minor (but annoying) changes, it was also the OS/2 Presentation Manager API.
- tjalfi 10y agoCharles Petzold wrote a new 16 bit app for Windows 1.0 to celebrate the 20th anniversary of Windows. The source is at http://www.charlespetzold.com/etc/Windows1/ http://www.charlespetzold.com/etc/Windows1/
- est 10y agoDoes this mean we can write a single binary with GUI which is valid in ELF/COM/Mach-O ?
- mschuster91 10y agoHmm. ELF and Mach-O should support fat/multiarch binaries IIRC (Mach-O certainly does, it was used in the days of Apple PowerPC=>Intel transition, not sure if it's still supported though), and I think it should also be possible to create COM/COFF binary that can be interpreted and/or run by Linux/Darwin kernel.
- currysausage 10y agoSlightly off-topic: if I want to learn developing Win32 applications, what is be the best place to start and where do I find comprehensive reference material? I find the simplicity and responsiveness of Notepad2 and similar applications very impressive. Should I get Visual Studio 6.0 or is a MinGW workflow [1] the way to go? Is MSDN still usable as a Win32 reference or is there some old go-to Win32 bible that I should look for? [1] http://www.transmissionzero.co.uk/computing/win32-apps-with-mingw/ http://www.transmissionzero.co.uk/computing/win32-apps-with-...
- dom0 10y agoProgramming Windows, 5th Edition (1998) is still practically completely valid, although it does of course not mention anything that came after it.
- satysin 10y agoPetzold's book that dom0 mentioned is/was the definitive Win32 reference albeit very dated now. It obviously will not cover anything in Windows 2000 and later(!). MSDN is still the go to place for all Win32 documentation although it can be tricky to find exactly what you want as MS prefer to push you towards .NET related stuff. Even finding plain C++ can be a pain with them pushing you towards Android C++ development by default for some reason?! For software you can go with MinGW-W64 or Visual Studio 2015 Community (you will need to do a custom install and select the VC++ tools as they are not included by default anymore). I used theForger's Win32 tutorials back in the day to get started http://winprog.org/tutorial/ http://winprog.org/tutorial/
- userbinator 10y agoThere's also "win32.hlp" if you want an older, yet offline reference; it's from the days of 95/NT 4, but surprisingly complete as most of the GUI functionality was already available back then. The recent versions of VS are somewhat more difficult for generating single-file standalone executables which run on OSes older than Vista.
- 10y ago
- raverbashing 10y agoIt feels like cutting a tree with a kitchen knife. Too complex to use directly
- coolgoose 10y agoI'm a bit fascinated by the possibilities exposed in the simple demo. Having right click system menu options that you could extend in what for me is a simple syntax is awesome :-)
- bluedino 10y agoFor added fun, do this on a IBM AT with dual floppy drives. Bah.