Building a new Windows 3.1 app in 2019: A Slack Client
yeokhengmeng.com
yeokhengmeng.com
In the demoscene this would be a disqualification as it's 676 bytes over the limit, but in this case I'll overlook it because of the sheer awesomeness of what you've done (and I'm sure trimming off 676 bytes wouldn't be too difficult ;-)
More seriously, this is an excellent proof-of-concept that a Slack client does not need to use hundreds of MB of RAM and consume most of a modern CPU core to provide its basic functionality. I'm a long-time Win32 programmer who started in the tail-end of the Win16 days and one of the things I've wanted to write if I had the time and need was a Win32 native Slack client, to show that it can be done with far less resources, but you've gone even further with Win16. Win32 has native TLS support (via SChannel library, not well-documented but examples exist) and you'd be able to even use it practically (32-bit applications will run on all current versions of Windows, both 32 and 64-bit.)
Note that C89 only prevents declarations of variables in the middle of a scope; you can simply create an inner scope with new variable declarations at its start. Like so...
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
...
}
Another small tip: if you make it a dialog-based application, you won't have to bother with WM_PAINT and drawing text yourself --- you can just make the "statusText" and "settingsText" edit controls, and use SetWindowText (or SetDlgItemText) to set their content. They will paint themselves automatically just like the listboxes that you used for the chat contents and userlist. At least you'll save some of those 676 bytes that way...Creating a native Windows app to mimic the Electron Slack client would not be a trivial task.
In my experience, Electron applications seldomly follow the UI conventions of the host OS or offer much in terms of integration.
If the desktop app is really just the web site in a locked-down browser, then what benefits does this offer to just the normal web page?
As far as UI inconsitencies go, most libraries I have used for native apps (Qt, Swing, Tk, etc) also do not feature UI elements that are consistent with the OS. Many developers simply can't afford to support multiple UIs just because they subjectively look a bit better.
Huh? Okay, maybe Swing doesn't support native-looking widgets (I have less experience with it), but I can personally attest that Qt and Tk (or more precisely Ttk) apps nowadays use a platform-native look-and-feel on Windows, macOS, and Linux alike, by default (i.e. with zero effort on the part of the app developer). It might not be absolutely pixel perfect, but it's way closer than an Electron app.
And just because it's electron doesn't mean it's inherently Cross-Platform look at discord for example It took too long for a initial desktop client to be released and then it ha issues with things like screen sharing not working as expected
They could but finding engineers with that kind of experience would be harder and cost a lot more. Far easier to retrain web frontend engineers.
"But I already know Javascript, it's too hard to figure out something else"
It's not like Maya, Steam, Chrome, Firefox, Skype, Adobe Reader, Houdini, DaVinci, Nuke, TeamViewer, Blender... haven't been working on Linux for ages (or more recently Bitwig, Reaper...). And conversely it's not like every Electron app has a linux build.
Later, at a different job, the UI was Electron based, but designers no longer worked in HTML, they used some other tools and it had become the job of engineers to write the HTML and CSS to match.
These trends seem to be driven partly by conventional wisdom about the lowest common denominator among young people in the workforce, e.g. javascript and html are so much easier, let's build everything on those, and next thing you know those have become a given and the next crop of kids will use something new on top of that. Or maybe something like QT will win and native code will become a first class citizen again with secondary support inside browsers via WebAssembly?
That's funny, because it's exactly the type of job I'd love doing --- and I have been working on stuff like that (native code, mostly Win32, with some hardware/drivers/embedded stuff) for a long time; if you haven't guessed already, I try to stay very far away from the web stuff, even though I know HTML/CSS/JS and can use it if needed.
At least with Electron you’re essentially forced to style everything - and ever since Windows 8 (or Windows Vista) Microsoft has been actively uglifying native widgets.
Still Java feels speedy, I think because it is compiled and doesn't need wacked workarounds like not having non-floating point numbers.
Update: ah, Microsoft released their own port in 1997: https://www.cnet.com/news/ie-gets-java-for-windows-3-1/ - I wonder how long they maintained that for.
which is funny when you see that Qt runs on microcontrollers now.
Even at an absolute worst case it still beats the pants off Slack.
An earlier blog post shows this http://yeokhengmeng.com/2016/09/windows-for-workgroups-3-11-...
Wikipedia says "However, no single process can use more than 16 MB.". Not sure where is the source of that though.
It’s a limitation from the 286 Protected Mode.
You don't call the raspi an SoC, and it's debatable that you'd call a prototyping platform like Arduino an MCU. The MCU is the main Atmel AVR, Microchip PIC, or similar part that drives such a board.
If you’re so sure that this is possible, then where is the Electron competitor which allows us to build cross platform applications like this, with the same levels of productivity and a consistent and decent user interface? No one needs to be convinced that a native Slack client for each platform would be much better, I wish they would build those clients. The problem is most companies can’t reasonably justify the costs of building multiple native clients when a single cross platform one is good enough.
Lazarus can use the Windows API on Windows, gtk/qt on Linux, and carbon/cocoa on Mac.
There is also a custom drawn mode that draws the GUI directly rather than using platform apis. That also runs on Android, but it not maintained anymore, so only up to Android 5 or something
Delphi is supposed to run on Android and iOS.
And Delphi 1 ran on Windows 3.1, so you could have used the same GUI since then
Shhh! Ixnay on the Lazarusay. If people find out, I'll lose my magical secret weapon for blasting out little windows gui apps.
Seriously though, if you ever find yourself needing a few buttons on a windows desktop that do simple things, Lazarus is amazing for whipping that up in a few minutes and still looking professional.
Both are C++: developers are more expensive to hire, and stuff takes more time to develop and debug. I'm proficient in C++ (programming for living since 2000), but I wouldn't pick the language for 2D GUIs in 2019.
> GTK+ can be programmed in Vala
Picking a non-mainstream languages is risky. Harder to find developers. Way more likely to find bugs in the toolchain and these can easily cost weeks to fix.
Have you seen the state of Javascript 'ecosystem' and job market?? Both statements are false.
The real reason is that C++ toolkits don't have platform and device independence. HTML and CSS are really good and powerful design tools, especially compared to composing raw pixels like you'd (essentially) be forced to do with Qt and GTK.
Let me correct: GTK+ is not C++, it's C. Qt is very cross-platform: it supports about 10 platforms, including Linux, Windows, and macOS. You are not doing anything close to compositing raw pixels in Qt or GTK+. They have layout managers that are specifically made for typical application UIs, and they have lots of ready-made widgets. Qt also has QML, which is a declarative UI descriptions language kind of like HTML/CSS but much more productive because (gasp) it's actually designed from the ground up for applications, not websites.
Which one would you recommend?
Cross-platform story is complicated, though. I have good experience creating a custom GUI framework for embedded Linux: drm/kms, gles, NanoVG, [DllImport], everything on top is custom C# code in .NET core 2.2. But that approach is not for everyone. I only needed 10-15 screens with simple GUI on them, it’s a 5” touchscreen with no other user-facing devices. Creating more advanced UX this way would consume too much time.
There’re Avalonia and Xamarin. Didn’t used them at that time because I needed full-screen GUI for a single-application Linux, without any desktop environments or user mode OS components. For desktops and especially mobile apps they might work OK.
It’s unpopular opinion here, but I think Electron is not that bad for GUI, esp. when writing TypeScript instead of JS. I think it’s similar story to Unity3D or PHP: low entry barrier attracted inexperienced programmers, then the whole ecosystem is judged based on the output of these inexperienced people.
Qt, as well as Windows, macOS and Linux actually can do Android [0] and iOS [1], and Web is halfway there [2].
[0] https://doc.qt.io/qt-5/android.html
You know all of the arguments against Electron that people trot out about how it's not real native, and it doesn't follow the right UX conventions or paradigms? Qt on the web is exactly like Electron on native, except way worse and without any sign that it's going to improve, because fundamentally Qt is structured around the idea that it should be able to spit out a binary blob of pixels instead of hooking into web-native primitives like the DOM.
Look into something that's showing more promise, like .NET and Razor. The Rust community is also doing some good work here, although I don't know that they have any UI frameworks that are mature enough to be reliable in an enterprise setting.
These aren't true cross-platform efforts yet, since they're still forcing you to think about HTML. But if I was going to bet on any project ending up with a real cross-platform solution that felt good on the web, some kind of export option from an Open Source Windows Forms or similar is probably what I would bet on. Either Microsoft or (possibly) the Rust community are the two parties that I think are most likely to end up producing a true native UI toolkit that can actually export to the web in a usable, acceptable way.
[0] http://www.beeware.org [1] https://dan.yeaw.me/posts/gui-widget-for-beeware/
[0] https://github.com/otya128/winevdm
It would have been relatively straightforward for Microsoft to support 16-bit on 64-bit, but they decided not to. I can't help but feel that that is just more evidence that whoever is running Windows development these days hates everything that used to make it a good desktop.
Back when 64-bit Windows came out (with XP and Server 20003), the adoption was pretty small since most applications were not 64-bit and did not need 64-bit address spaces. Microsoft saw the opportunity to kill at least one backward compatibility burden by not even trying to support 16-bit for x64. They figured, rightly, that by the time x64 became widespread, 16-bit would be obsolete.
Don't believe I said otherwise.
> This has nothing to do with "whoever is running Windows development these days"
> Microsoft saw the opportunity to kill at least one backward compatibility burden by not even trying to support 16-bit for x64.
These two statements are at odds. Microsoft used to take compatibility extremely seriously. It would have been relatively trivial to allow 16-bit applications to run, and obviously there is desire to do so since WineVDM exists, they just arbitrarily decided not to.
I suspect this is because they've become infected with developers who use Linux a lot and think nothing of breaking compatibility every release, let alone in cases like this.
It didn't exactly run 16-bit installers. https://devblogs.microsoft.com/oldnewthing/20131031-00/?p=27...
> Write your apps in Python and release them on iOS, Android, Windows, MacOS, Linux, Web, and tvOS using rich, native user interfaces. Multiple apps, one codebase, with a fully native user experience on every platform.
I have a python script that I want to deploy as self-contained app for windows and osx with a gui. Finding a framework that works, is decent to use, doesn't need hundreds of MBs of dependencies, and has rich text support is...not easy.
I'm still trying to figure out if there's a GUI that supports different text with mixed colors and features out of the box, and that's not horribly broken in OS X
I was actually thinking of giving it a go, but the idea of a Python backend and a Delphi frontend is as attractive as recoding everything in ASM.
Slack calls don't work reliably in Chrome/Electron on linux anyway, so no loss here.
Edit >> looks like JavaFX WebView is a thing now, plus the jxbrowser embeds chromium in a Java App... not sure of the performance of either of these implementations
That's the biggest lie ever, with these newfangled "cross-platform" solutions.
I want to watch the guy who has to sit down and port electron to a platform it doesn't run on yet. It's just a few lines of code, right?
Java had the same problem, everyone who ran Linux in early 2000s remembers. It's still not something I would want to port, but at least it runs on more systems ootb than electron.
The truth is, everybody knows about Qt, GTK and so on, and everybody knows Electron is heavy but you have to be realistic. As a company do you want to spend that much money hiring a ton of C++ developers over a much longer period of time, or do you go for the solution which, while not ideal, allows you to develop a cross platform app in a much shorter time?
These days many people run Electron apps without even knowing it, showing that it's an ok solution.
I don't think I said all that
> As a company do you want to spend that much money hiring a ton of C++ developers over a much longer period of time,
This I think is a big assumption. Making a GUI isn't really that difficult. Most of the time in a program doesn't go into making the actual UI. I never hear someone who is experienced in making UIs say that electron saves them so much time, it is always people assuming it takes an army of C++ people to do what one person can do with electron, which is bizarre, especially over the course of something that is more than a prototype.
Kind of: "inexperience", "lack of research", "don't want to learn C++"
> Making a GUI isn't really that difficult.
Also a big assumption, especially for cross-platform GUIs.
It is not a big assumption, I've done it many times. What is it that you think electron gives you that cross platform GUIs don't have? Making the actual UI is usually pretty trivial, it isn't even logic, just data through function calls.
> false sweeping statements
OK.
Without the benefit of modern libraries and languages, I had to read up and take care of many low level details, socket programming, HTTP, JSON parsing, UI design in code all under tight memory constraints. Nevertheless, it was a terrific lesson in understanding how things work under the hood.
I had to do things the old-fashioned way reading books and header files due to the dearth of online documentation. I can empathise with the plight of the programmers of yesteryears who had to code without the benefit of online search engines.
With this blog post, I hope you'll find it interesting to learn about developing a modern-ancient app for Win 3.1.
https://github.com/yeokm1/w31slack https://github.com/yeokm1/http-to-https-proxy
I feel "old-style" documentation is much better than we have now. My most productive _python_ only work times were when I had only the python .hlp file and a _physical_ paper book.
What are your impressions?
But now the amateur documentation writers are competing with the professional ones; the quality of the professional documentation is still as high as ever, but it can be drowned out by the amateur quality documentation.
All in all, finding the information you need is MUCH quicker via a search engine, but the signal-to-noise ratio is lower.
One of the more memorable WTFs I've seen is this, which is still wrong as of this post:
https://docs.microsoft.com/en-us/windows/win32/api/wininet/n...
Compare to the old version of the page on MSDN:
http://web.archive.org/web/20080828050103/http://msdn.micros...
See what's missing? The newer version is not the correct one... in "migrating" the document to the new site, for a reason that completely defines all rational explanation, the return type of the function declaration became void. There are plenty of pages on the new site with this serious error, and they've remained unfixed for well over a year. People report such problems on their GitHub, and they get fixed --- individually --- as they're reported, but it still boggles the mind how such a blatant and widespread error could go through (and the old, correct, content deleted flippantly) without someone in power shouting "STOP!":
https://github.com/MicrosoftDocs/windows-driver-docs-ddi/iss...
Also, what's the purpose of the people who will answer nearly any question with a very low-quality (but wordy) answer? What are they getting from this effort?
You see it on SO too, people answering basic questions 2 seconds after they're postedd with long pastes from documentation that are sorta related to the original question.
It depends on which docs you are looking at, but some are very broken, with broken links, broken tables, broken text formatting...
Do you know of any way to get a handle to the old docs or perhaps a full MSDN dump of 3 years ago or so? (other than the web archive)? Perhaps the latest MSDN offline release or something?
I don't even mind paying.
I hardly google something in a week of work, since there is nothing online about anything. It is like heaven compared to other ”google driven” programming things I have done. I feel very productive pretty much all the time, even when debugging mysterious real time issues.
I thought porting a Python script to VB wouldn't be a big deal, but like you said, things youtake for granted like JSON and certain dictionaries are just lacking.
Not too long ago I remarked here on HN that I expected VB6 programmers might become in demand in the future (when, I don't know), similar to how COBOL programmers were/are.
Basically, for the need to convert apps, written internally for a business, from VB6 to something else (likely to VB.NET or C# - maybe on Mono - but there are other options too).
I expect this to happen when Microsoft finally kills off the VB6 runtime DLL - but so far they haven't; from what I understand, it's still available in Win10...
Doing things the old-fashioned way was harder but less was expected of you, time-wise. Getting a "database" (a set of BTrieve files, usually) set up would take days, editing on floppies, etc. It was just expected that making software was a long process.
It's designed for compatibility, and I've tested a lot of Netscapes and IE4, but nothing on Win311 yet.
If you want to leave a comment, you can do so right on the message board. It should work, more likely with JS off.
Many of the 3.1-era browsers didn't have a concept of JS yet. If you're relying on noscript at all it won't work.
I did try and check if this was the case, but both links in your profile that it could have been lead to "not found" dreamhost sites.
<noscript> works just fine in pre-JS browsers, at least all of the ones I've tried.
It works exactly as designed: Text between <noscript> and </noscript> is displayed in browsers without JS enabled (or supported).
I am not aware of any browsers where this is not the case, and I've tested in many, including Mosaic 1.x-3.x, NN 1.x-4.x, Opera up to 3.62, and others.
(You probably happened to visit my site during an upgrade. Sorry about that.)
Strict validation of HTML came later with XHTML, but AFAIK all browsers which understand XHTML also understand JavaScript.
However, HTML 2.0, which you can find specified here [0], and it specifies the "ignore" behaviour. Short of spinning up an old VM, I think I'll trust that my memory hasn't failed me.
From RFC 1866:
> markup in the form of a start-tag or end-tag, whose generic identifier is not declared is mapped to nothing during tokenization. Undeclared attributes are treated similarly...
> For example: > <div class=chapter><h1>foo</h1><p>...</div> > => <H1>,"foo",</H1>,<P>,"..."
Gives just a 404.
(In fact, AFAIK even in modern Windows you should avoid taking too much time to process each window message, since blocking the event loop thread makes the UI for your program unresponsive.)
You are guaranteed no context switches unless you explicitly request one - did it simplify some parts, or alternatively made it more complex? It's an asynchronous application.
I had dual screens at home in late 1995 for sure, can’t remember if I used a dual screen setup any earlier than that.
10 points (well, an upvote, I guess) for anyone who knows why the Windows DOS-mode installer says "Press F3 to exit"
When I first saw that UI in 1990 or so, I was so confused how one program could accidentally cause another one not to respond. And how all the filenames had to be in 8.3 format.
Amiga had spoiled me.
Press F3 to exit setup without rebooting; A bug in the MS-Client installer prevents a file necessary for Windows 3.1x support from being installed. This isn't necessary if running solely under DOS, but it doesn't hurt in anyway, so let's install it just to be safe.
Warning: [Omitted] source link is blocked as malware by Firefox, quote gleaned from [DDG] search results.
On the other hand there is a related issue: on DEC (and some other) terminals with LK201-style keyboards (which in turn inspired the "modern" PC/AT keyboard layout with F1-F12) the keys in positions of F1-F5 had fixed functions. This is the reason why there are about four different escape sequences across vt220-compatible terminal emulators for F5. There simply was not any DEC terminal that had F5 on its keyboard (F1-F4 are almost always mapped to PF1-PF4).
Maybe this would be a good opportunity to stop for a moment and reflect about whether or not the industry is really moving in the right direction.
Alas, he "cheated" for it with a proxy app. Can't say I blame him, since it's probably about as much work over again to get modern TLS 1.2 working on such an old Windows.
I think the work to get TLS 1.2 working will certainly dwarf the work on this Slack app.
Seems to me you'd pretty much have to write a simple TLS 1.2 or 1.3 client by hand, or port an existing simple implementation.
But yeah, makes sense as it would be way too much work.
It runs in Windows, Mac and Linux
It's also probably possible to use a current compiler, maybe clang or gcc, to compile such code (officially only up to VC++ 4.2 is supported), although it might require some hacks.
The sixth edition on words begins to use the. Net CLR and other non-native toolchains as Microsoft changed them. So, those are less valuable to me.
If you want to do native Windows development, that is probably the single best book you could buy.
I am going to be using this line a lot in the future.
(The Linux x86 maintainers are semi-seriously considering deprecating the horrible machinations needed for 16-bit on 32-bit to work, but 16-bit on 64-bit Will be supported for the foreseeable future.)
/me feels an urge to read Unauthorized Windows 95 back to back.
Didn't crash and was smooth as butter.
Initially turned out that it had been set to RS485 mode, and I didn't have an adapter, and I didn't even know if it worked if I was able to get it into that mode. So with the help of a sympathetic engineer at SICK, he had me send to unit to them and he reset it (to RS232) and tested it. When I got it back, I tested it with the machine again and it worked perfectly. He didn't charge me anything for the service.
You don't see that kind of support anymore - almost no company will say "yeah, sure, send us a unit you bought second-hand off Ebay to us and we'll take a look at it, fix it, etc - and no charge to you, either - even though you're just a hobbyist and have no support contract" - it shocked me.
Have you kept a nt4? Do you still use it? What do you think is the closest equivalent: win200, reactos??
O tempora o mores!
I'm getting old...
currentToken = tokens[index];
tokenSize = currentToken.end - currentToken.start;
if(tokenSize <= 0){ continue; }
printf("Current token %.*s\n", tokenSize, startOfJson + currentToken.start);In actual fact, I'll have to copy the data to a char array to be sent to display in the listbox.
> hence I need to use those values to copy out from memory to a separate char array for printing purposes. Certainly not so trivial.
https://en.wikipedia.org/wiki/Turbo_Pascal#Turbo_Pascal_for_...
Hey, what's wrong with Trumpet Winsock? :-)
They needed some way that you could be waiting for either window messages or socket data. Otherwise your window would stop responding to input or repaint itself if some socket operation blocked.
I'm guessing that Visual C++ 1.52 has no code editing capabilities like Visual Studio?
I also use Git and sourcetree and they won't run on Win 2K.
Not true, you can downgrade the SMB version requirement in the Windows 10 registry.
I'm sure writing mIrc was not "zero pain" back in the day. And Jabber needs a XML parser which is more complex than a JSON parser.
Also, an IRC client is a joke, it can be compiled and built even on BSD 4.3, released in late 80's.
The suckless guys created some IRC clients in few lines, and the sj client is not that difficult.
Heck, you could write an IRC client with Bash and even with Netcat/ed.
Or even Delphi! Delphi 1 targeted Win16.
Unfortunately, it still doesn't work as good as before: text like `Object`s (no space between the ending ` and next text) doesn't work anymore, and according to Slack's support this is 'working as intended'.
Edit: oh, I see what happened now. We made a mistake, intending to set the URL for https://news.ycombinator.com/item?id=21831931. Sorry!