
Show HN: Counters – GUI for those who don't do GUI - okaleniuk
https://github.com/akalenuk/16counters
======
Evidlo
Cool idea. Here's how to do it in Linux with files:

    
    
        # create the "counters"
        touch {01..16}
        # use multitail to show all counters in a grid, 4 columns
        multitail -s 4 *
    

Now you can write to any of these files

    
    
        echo hello > 01
        echo world > 16
    

The result looks like this:
[https://i.imgur.com/yVWWMfr.png](https://i.imgur.com/yVWWMfr.png)

You can also tell multitail to automatically rescan the directory and display
new files

    
    
        # check current directory for new files once/sec. match any file
        multitail -s 4 -q 1 "*"

~~~
Phrodo_00
You can also have nice dialogs by using dialog/xdialog/zenity. For example,
you can use named pipes and get a nice progress bar:

    
    
        mkfifo progress
        cat progress | zenity --progress --text='progress'  --percentage=0 &
        echo 10 > progress
        sleep 10
        echo '# Done!' > progress
        echo 100 > progress
    

[https://help.gnome.org/users/zenity/3.32/progress.html.en](https://help.gnome.org/users/zenity/3.32/progress.html.en)

[http://linuxcommand.org/lc3_adv_dialog.php](http://linuxcommand.org/lc3_adv_dialog.php)

~~~
brbsix
I always use YAD, a much more feature-filled fork of zenity.

[https://sourceforge.net/projects/yad-
dialog/](https://sourceforge.net/projects/yad-dialog/)

------
saagarjha
> The buttons seem misaligned but there is logic in it. The buttons that has
> to do with the coutners are closer to the counters. And the buttons that
> expose the window handler are closer to the window handler. And yes, the
> number on top is the window handler.

I'm having a bit of trouble understanding this, since I can't see how this
works. How does [C], which "copies a C-style SendMessage template to the
clipboard", have anything to do with exposing the window handler?

~~~
tastroder
If you look at the SendMessage code examples, they contain the window handle
as the first parameter. Looks like that's a convenience feature to reduce the
amount of typing required to get data into the target. It basically generates
code to communicate with the instance you pressed the button on I believe.

------
weinzierl
I've heard from game dev circles that some use _Dear ImGui_ in the same spirit
- as quick ad-hoc sort of GUI. A printf on steroids, if you will.

~~~
akx
That + this post gives me an interesting idea... a local network interface for
ImGui for environments where you don't have a native window, or there are no
convenient bindings for ImGui.

~~~
tom_
See also imdebug:
[http://www.billbaxter.com/projects/imdebug/](http://www.billbaxter.com/projects/imdebug/)

~~~
codetrotter
From the name and context I was expecting something directly releated to
ImGui, but imdebug is not directly related to ImGui nor to immediate mode GUIs
in general in any way. Still interesting however, even though it wasn't what I
was expecting.

~~~
tom_
It was the network interface aspect that made me think of it.

------
tastroder
I wouldn't personally use this since my preference usually goes towards
terminal UIs but I love seeing these personal productivity tools that people
come up with. Nice work (and kudos on actually maintaining readable assembly
code)!

Isn't it annoying to have to change out window handles manually all the time?
Or did that just become muscle memory after using the concept for that long?

~~~
okaleniuk
I try not to keep the SendMessages for too long. We actually have a Linux
gate-build at work so they only live on local machines.

But every once in a while I spawn them all across the code to hunt some bug,
and then I think I got it, and I do the victorious "Aha!" and close the
window. And, of course, it's not it and then yes it gets annoying to update
the handlers.

~~~
mst
A thought sprung to mind: In *n?x environments, if I were implementing
something like this I think I'd do it using an env var for sync. Think
something like:

    
    
      $ eval $(start_counters); # start process, print 'COUNTERS_ID=...'
      $ ./myapp
    

i.e. "stealing the way ssh-agent works for fun and profit"

I'm suspecting you already thought of this sort of trick and rejected it as
not worth the extra complication for the rare annoyance, but since it didn't
pop into my head until hours after originally reading this comment I figure it
was worth noting just in case.

------
pjc50
The ""deluxe"" (ie far more complicated) version of this might be to use ETW,
which is one of those extremely Microsoft APIs that's both powerful but obtuse
and can only really be learned from the one blogger providing examples. Which
in this case is the amazing series of posts from
[https://randomascii.wordpress.com/2015/09/24/etw-
central/](https://randomascii.wordpress.com/2015/09/24/etw-central/)

ETW would also work in those rare situations where SendMessage() doesn't, such
as from a device driver, and can more easily be logged.

------
hanniabu
From the title I thought it would be some type of data dashboard with a simple
conf file to grab all the data. The conf file could have options like
"endpoint" for the API endpoint, "type" for the chart type (bar, plot, pie,
etc), "target" for how to target the data in the response (res["someData"]),
or "targetx" and "targety" for graphs, "labels" and "axis" for assigning
labels to the data, and "style" for selecting different variations for the
graphs/chart such as solid/dotted/dashed for line types.

------
rs23296008n1
This reminds me of those old carpenter tools and worn workbenches. Deceptively
simple and specific but its really a complex multitool full of subtleties
embedded mostly in _how you use it_ rather than in another GUI or command line
option.

In assembly language _and_ targeting windows as well. Novelty++.

------
stiray
Ehm, this just how windows work, you are having a hwnd (window handle) and
message with optional parameters. There are hundreds of messages and WM_USER
just defines start of custom defined messages. Typically you define your
custome message as WM_USER + arbitrary number. And you also have PostMessage.

~~~
okaleniuk
You're right, it is generally a good idea to use messages for this. It is also
better performance wise to keep all the dispatching in one place.

But I tried that at the very beginning and it was rather inconvenient since I
had to drag defines to every place I want to send a message from. "WM_USER +
'R'" might have worked but it's worse than "WM_USER, 'R'" aesthetically. And
there is an extra parameter anyway.

PostMessage is also better for writing things to the counters since it's
asynchronous. But it doesn't work for reading. It's just more convenient to
have one function do both but of course you can post messages too.

It's a silly tool anyway. Basically made of compromises.

------
vorpalhex
Given that this is <500 lines of assembly this is frankly amazing given the
overall complexity of the layout. Very clever.

------
29athrowaway
gnuplot, graphviz, ministat can help you visualize stuff fast.

For interactive stuff, you can create a HTTP server and send requests to it
from a web UI. For example, using this: [https://github.com/yhirose/cpp-
httplib](https://github.com/yhirose/cpp-httplib)

~~~
weinzierl
gnuplot and graphviz both are a staple but I've never heard of ministat so far
- looks really useful though.

------
janci
This is neat. From time to time I use a thing I call livedisplay. It is a http
endpoint that you can send json message to an it will forward it to web
interface via websocket. Obviously much more overhead than 16 Counters, but
works on network and cross platform.

------
fareesh
I can't relate to this environment or workflow but off the top of my head if I
wanted to do something like this I'd use some kind of pub-sub and publish to
it from one place and read from another - is that what this is ? Or am I
missing something?

~~~
0xffff2
Yes, except there isn't really a subscribe step so it's really just "pub". You
are manually publishing messages to a static window handle.

~~~
fareesh
Got it

Is it not possible to just use redis or some windows equivalent for this kind
of requirement?

------
bmn__
Oleksandr, I can't help but be reminded of
[http://okcancel.com/strips/okcancel20031010.gif](http://okcancel.com/strips/okcancel20031010.gif)
:)

To be fair, your software probably was not intended to be used by anyone else
and publishing it to Github is just for sharing the underlying idea.

------
momofarm
MFC, still alive? In this “web” world, who still code use MFC framework?

~~~
FpUser
Yours truly and many, many others. I do not actually use MFC as I only use C++
for servers. GUI things in my case go to Delphi/Lazarus. There is a whole
world outside of that web juggernaut.

~~~
momofarm
Delphi! Whaaaaat a surprise !

I still miss MFC/windows programming a lot, I think in many ways it's quite
efficient.

But for job seeking it's not a good idea, opening for windows gui is quite
rare.

Maybe I should setup a web(!!) For lonely job seeker on windows programming /
and Delphi/lisp/scheme / all other good oldies forgotten by rest of the world.

~~~
FpUser
Delphi is quite popular still in Europe. Also it is not just Windows.
Delphi/Lazarus produce exe for all the major platforms. I was doing some GUI
app for Raspberry Pi and I had Lazarus IDE running right there, along with
debugging and all other goodies. Also I mostly develop products and are on my
own since 2000. Not much concern on my side about what all those big cloudy
companies think. Eff them ;)

