Tuesday, March 30, 2021

Resume (Continued)

Gdrive link

https://drive.google.com/drive/folders/1olhXSF0poL_gXIVF7fWYwECMO3ue8Bv8?usp=sharing


Certificates

Intro. to Game Development Certificate:

https://coursera.org/share/2df27b0a13d2bacd7519629aaede97b9

(or Gdrive --> intro-gd-cert.pdf)


Programming for Everybody Certificate:

https://coursera.org/share/364409601d3e661bcda520719912d876

(or Gdrive --> intro-python-cert.pdf)


Personal

Here, I list all the personal projects I worked on. Description-wise, I only add things I normally don't put on a resume.


Soul Calibur 2 AI Project (Updates listed below) 

2) (8-20 to present) I studied the Dolphin emulator code a few months back. I looked into a statistics method and some “animation range” idea I had for an AI, but it didn’t work out. I had a finite state machine idea. It works, but the scale is way too large. My last attempt will be to try to figure out how to track a program counter in the game’s assembly code. Maybe I can figure out some values that makes this AI possible. Anyways, I still like studying this.


1) (1-1-2021) I studied the Dolphin emulator code a few months back. I looked into a statistics method and some “animation range” idea I had for an AI, but it didn’t work out. I have a new finite state machine idea that I think works well. I see now this “AI” is too big to complete, but I still just enjoy looking into it little by little these days.


Debugging CS 152 Emulator (C, RISC-V Assembly; Feb. to March 2021)


Gdrive --> emul-fixes contains things I emailed to Professor Sang-Woo Jun. The "emul-fixes" folder has:

  windows_fixes (contains notes and emulator code)

  run1.jpg and run2.jpg (shows fixed emulator running)

  gcc_eecs.jpg (shows a friend trying to run my fixed emulator. It shows errors, but that's because the version of gcc there is an old one. He said it works on that version with certain flags.)


Programming Study Group (Group Leader; December 2017 – September 2018)

OpenGL Missile Shooter (C++, Visual Studio, OpenGL; November 2017)

Visual Studio Project Porter (Python, Visual Studio; October 2017)

Air Bomber – 2D Game (C#, Unity Game Engine; Jan. to March 2017)





Thursday, March 18, 2021

Lenovo 3306G2U Start BIOS Keyboard Fix?

Info:

Keyboard: Lenovo KB1021

Windows 10 

System Information App -> System Summary -> BIOS Mode = Legacy

Control Panel App -> Power Options -> Choose what the power buttons do -> Turn on fast startup (recommended) = checked


=============

 -wanted to enable virtualization in BIOS to run VM to help my professor debug a lab assignment





These didn't work, even if they seem both for Legacy BIOS mode:

1. How to enter the BIOS on most Lenovo ThinkCentre desktops - The easy way!

https://www.youtube.com/watch?v=JfugRhKbFBU

2. Computer Can't Enter BIOS? | How to Force It

https://www.youtube.com/watch?v=IMr5-mEbhTs








https://support.lenovo.com/us/en/solutions/pd024422-detailed-specifications-thinkcentre-m92-m92p-and-m82-small-form-factor

--> Hardware Maintenance Manual --> pg. 57 --> BIOS key is F1

                                 [[[In my edit below, it's a --different-- page.]]]

(

Edit 9/3/21 11:10 PM Link was broken. I searched "lenovo thinkcentre m82 hardware maintenance manual" in Google. I found this as the first result. It has the pdf: https://www.manualslib.com/download/462274/Lenovo-Thinkcentre-M82.html

In this pdf, pg. 59 has "Chapter 6. Using the Setup Utility Program" at the top. And it's there I can infer that "BIOS key is F1".







After a lot of trying F1 with "Restart" and "Shutdown", I unplugged a USB external drive and a USB hub from the front ports. I re-plugged the keyboard from the back port to the top front port. I did "Shutdown". I then tried F1 on "Startup", and now it magically worked. 

-However, after that, I plugged the keyboard to the back port again. I didn't re-plug the other devices. And now, after "Shutdown", that worked too. I'm pretty sure that didn't work before, as I said earlier. Maybe I wasn't pressing the right keys then?

-I plug the 2 other devices to the front ports now. Once again, I can't use F1. I called it a night. But now this morning, with the keyboard in the back port and the 2 devices in the front ports (the --original setup--), F1 works. 






I have no idea what's going on. I'm not sure if I even "fixed" anything. Some ideas:

-Maybe I really didn't repeatedly press F1. I was a bit frustrated when it didn't work at first. Maybe when I mashed multiple buttons, F1 did work, but another button caused some "Exit"/"Cancel" to run instead.

-I had a pending Windows update. I tried starting BIOS w/ it still pending. Maybe the update was important.

-When I plugged the keyboard into the top front port, when I started Windows, I got a notification about some "NETVISTA" driver being installed. When I plugged it to a back port, I noticed one time a "Lenovo Preferred Pro" driver was being installed. Now w/ this new driver, using F1 always works now?

-Sometimes I don't repeatedly press F1 fast enough or early enough. So sometimes it works, sometimes not.  

-On startup, maybe the computer needs to dedicate a lot of energy to purely startup. If I have multiple USB devices connected, let's say the computer prioritizes giving power to the front port devices over the back port devices. If the front port devices use a lot of power, a keyboard connected to a back port for example wouldn't get any power, so I couldn't press F1. 



Friday, February 5, 2021

Searching Phrases

 Someone with similar interests might be searching:

"i want to team up with someone"     (for the x86 assembly that I'm learning at the moment)

             (exact quotes)


Blender

Unity


learned programming back in high school

learning technical specifications

Cpp, C++, c plus plus, C

computer science, computer algorithms

computer internals

 

personal project

general science

science

science history

history of everyday life

Sunday, December 31, 2017

My Thoughts on Paper Index Cards

I've been using paper index cards that I've been organizing in alphabetical order to keep track of my notebooks. I like to write thoughts on various things in there, like OpenGL, exercising, and project ideas. I'd rather have one notebook to keep them in, rather than multiple. I don't want to have a dedicated notebook on exercising if I don't update it regularly. That'd be a waste of a notebook, in my opinion. And also, when I have a new thought that usually takes less than a page, I'd rather have a single notebook to write it down in rather than figure out which of multiple notebooks to put it in.

With that, I consider these notebooks more of "thought streams", where I write whatever comes to mind. And once in a while, I update the gdrive link to pictures of my notes. I started it back when I started this blog. I want to share my notes, and it's also easier for me to view them digitally instead of bringing all my notebooks around. I talk more about it in my first post on this blog.

Having alphabetical index cards has allowed me to easily find various entries. It's also easy to update. I just write an entry, and I can sort it into my set of cards quickly. However, I feel like I now want to use a digital form of indexing, with a txt file. I'd like to use the pictures I took of my notebooks more. I started out with paper index cards because I wasn't sure I was going to commit to indexing like this, but I've been doing it for a while now (I think around the beginning of my last university quarter). So I'm really comfortable with this, and I like it a lot. I now want to make it digital.

As I plan to use txt files now, I still want to make a post about this. I thought it was really cool to do this, and I don't think I'll rid of paper index cards totally. I'm considering making sets of cards for separate notebooks, instead of one giant alphabetical stack, like I have right now. Anyways, I'll talk about what I've done first, and then my thoughts on it.

About the Cards

Back at home for university winter breaks, I put my cards in an old pencil box. I used a rubber duck to prop the cards up.





With the cards propped up, it's easy for me to fan through my cards. The pencil box is from 5th grade, looking at the stick on the top of the box. "Mrs. Wong, Room 33". Dad was using it to store spare parts. I found it, and got his permission to use it.

I asked my parents to get the rubber duck back in my freshman university year. As my home is relatively near, they brought it to me one weekend when they visited me. I thought I'd get it because of the term "Rubber duck debugging". I've never done it actually, though I just thought it be nice to have one since I do programming a lot.

Just side stories I wanted to put here.

I use the rubber bands to wrap the cards up when I want to put them in my backpack and take them somewhere. That other grid paper piece isn't relevant. It was just a list of things I wanted to buy.



I organized cards in alphabetical order. started with actual index cards, but then I started using spare paper that I could find. Cardboard, grid paper, scratch, paper from mail. I was more interested in what I wrote on the paper cards, rather than how they looked. Plus, I thought it was a useful recycling idea.

Some of my entries are below:




While I don't like having separate notebooks for thoughts like these, I do categorize my cards if I need to. I write my thoughts about life in small, handheld notebooks that you can hold with one hand. Like memo pads. I put them in a "Life Notes" section. I write other thoughts in larger notebooks. The 10.5" x 8" kinds. I just call them "Practical Notes". For university, I've found that I like making index cards for class notes too. I made a "Class Notes" section for those. And I have a separate section for each of the 3 classes I took last quarter.

I added a photo below showing all the sections I made. I used paper and tape and attached tags to cards of the same size as those I write my entries in. So the tagged cards fit in nicely, and the tags still stick out.


In the entries themselves: I write three things:
  1. The name of the entry
  2. Which notebook the entry is from
  3. What specific page the entry is in

I don't think the date is important. The content itself is more important. So that's why I don't write dates. (And ya, I am a little lazy there too haha. I admit it's only a few numbers and slashes more. But it's what I'm comfortable with.)

I've varied in how I number my pages. I tried different ideas for them. In the "Memory: Draft rewriting in English class" one, I wrote "6.10" for a page number. It's an idea I tried, having major sections and minor sections. I initially wrote only the major section numbers, then wrote the minor section numbers in when I found I was making cards for that major section. I may talk about it more in a separate post. Now, I'm just numbering my pages with regular numbers. But I still enjoyed trying out a different numbering idea.

As I ended up having a lot of notes, I used multiple notebooks. Having a page number wasn't specific enough then, so I labeled my cards with the name of a specific notebook it was in. Like for the memory card, I labeled "GB110217" for the notebook name. I had that mean "Green notebook that I started on 11/02/17". It's my own notation. I'd rather write something more shorthand like that since it's easier for me.

For the "Life Notes" and "Practical Notes" sections of index cards, I added separate cards at the beginning, each explaining a shorthand name I used. For the "Class Notes" section, I just wrote entries on the section cards themselves, because I wasn't intending to use so many notebooks for one university quarter class. 



And that's the general outline of the card system I made for myself.

Thoughts

I'll be trying to use a digital listing with txt files now. Still, looking at it now, I like the alphabetical index-card idea I formed over last university quarter. I'll try matching its flexibility in the txt files.

Had computers not existed before, I think I'd be fine developing these cards more. I'd be considering that as my sets get bigger, I'd then either move cards into other sets. Or I'd manually copy them. I'd probably ask someone else to do it and pay them for it with spare money I had.

I'll still probably use paper index cards when I'm using a notebook I haven't archived yet (taking pictures of it and replacing it when it got full). I still think they can be handy as a sort of "offline copy" that I can carry with a paper notebook. Like, maybe I just want to look at a specific notebook that I take when I carry my backpack around.

In that case, I'd make separate sets of cards for separate notebooks then, instead of focus on combining them into more general sections like "Practical Notes" or "Life Notes". I'd still include the name of the notebooks in my cards in the event that I do want to combine my cards altogether, or to use if I accidentally mix cards up.

As I try out using txt files now, I'm just "starting fresh". I won't try to manually copy every paper card I currently have now. The pages definitely to match up with the image filenames my camera gave my pictures when I digitized my notebooks. And I haven't fully numbered all the pages in certain notebooks either (this is part of what I may talk about in that separate post I was writing thoughts about earlier). But I won't throw my current set away. I'll keep it for memorabilia.

And that's all. I noticed with more posts like these, I've been making more of an outline for myself before writing them. Didn't use to do that before, but never thought I needed to be that thorough back then. I guess with bigger hobby programming and writeups, I've gotten used to outlines. They're pretty helpful. Anyways, as it's the 31st, here's to the New Year and to striving to be different. : )

Thursday, December 28, 2017

Continued OpenGL Forum Response on GLFW details

I made this blog post as a continued response to my intended reply to a question thread on the OpenGL forums called "Some questions about a first example of OpenGL". In this question, a user named Tomyfr was asking about some inner workings about GLFW, mainly about glfwPollEvents and how other GLFW functions are related to it.

I saw this thread, and I thought I could help with this before working on a personal airplane simulation project with OpenGL. While writing my initial reply, I realized I wanted to write a lot. I felt like if I kept writing this and it became too large, my reply would be too inconvenient to see on the thread. So I thought I'd continue my reply here. It's been a while since the post appeared, but I still think this would be helpful. And it could be useful to reference this if someone asks a similar question.

In the response below, "you" is referring to Tomyfr. I'm still writing this mainly in the form of a reply, not as a general blog post.

=====

As I'm writing an extended reply which will probably be long, I'll first post the main questions I want to focus on here, based on the thread and my initial response that'll I put directly in the forums:

Main Questions I Focus On:
-Why is glfwPollEvents needed? You thought processInput makes this unnecessary.

-I mentioned glfwGetKey and glfwSetWindowShouldClose in my initial reply. How does that help with insights on your processInput function?
-How is the Esc key related to glfwPollEvents and your processInput function?

-How does glfwSetFramebufferSizeCallback work? How are arguments passed to the width and height parameters of the callback function?
  -How do you know to set up your framebuffer_size_callback function as you did for glfwSetFramebufferSizeCallback?
  -I mentioned the WM_SIZE message in my reply. How does this give insights into the glfwSetFramebufferSizeCallback function?

I'll try to answer those in the order I wrote those. In response to those questions I came up with for myself, I plan to write my reply based on these main points:

Main Points I Want To Respond With:
-From what I looked into, I'm guessing glfwPollEvents and the other related GLFW functions are based on two things:
  1. The event-driven system that the lower-level Windows API is based on and that GLFW abstracts (I assume you use Windows. I can only write from that perspective now, anyways. It's probably similar on other OS's).

  2. C/C++ callbacks, which is language specific, not OS-specific.

-Analyzing the GLFW source directly is how I made my guesses about the GLFW functions you were wondering about and how they are related to the Windows API that GLFW abstracts.

-I recommend trying Windows API. It’s powerful and gives amazing insight, including insight about API’s that abstract it. I added some resources at the bottom of my post.

My Main Reply is Below:

I want to first talk about the Windows API (Winapi) before talking about glfwPollEvents. I think that'll help the most.

Winapi's event-driven system

I want to focus on the event-driven system. What I want to write isn't a tutorial on the Windows API. If you haven't tried it yet, sorry, I won't explain all the getting started stuff. I'm going to try to focus on the event-driven system itself and less on actual code. I'll try to write it in a way to explain the general idea.

What I'll do to try to make it easier to understand is:

1. Use the "A Simple Window" sample code from theForger's Win32 tutorial and make a few changes. My reasons for this are:

a. If you try the tutorial, my code may be easier relate to.

b. It's been a long time since I've written Winapi on my own. I've been focusing on OpenGL on GLFW for a while, so I'm pretty rusty. Changing tutorial code will make it easier for me too.

2. Link you a complete VS 2015 solution to samples I may talk about here, so you can just run them without thinking about specific code. (I remember one of your past posts saying that you use 2017. So you should be fine w/ my 2015 solutions.)
  -The VS 2015 solution, as well as all other files and credits I wanted to include, are mentioned at the bottom of this post. Here's the link now, to my dropbox folder, for convenience.


So anyways, Windows API is an API to do low-level window management and systems programming on Windows. Window management has it such that an application (a single .exe) can contain zero, one, or more actual GUI windows that you can see.

(I show these in the no_window, one_window, and mult_windows projects in the VS solution I link above.)

In the case of more than one window, like in the mult_windows project, you consider that you have a parent window and child windows managed by the parent window. Child windows can be enclosed within a window, like in that project, or they can be separate, like in the tool windows you see in the GIMP photo editor. Separate or enclosed, as child windows, they close when the parent window that manages them closes.

Window management is based on an event-driven system. Not all of Winapi is event-driven (ex. phone programming), just the window management part. Window management is only relevant if you actually have a window in your application. So the no_window project doesn't interact with the event-driven system.

In an event-driven system, your Windows OS sends events to your application based on either user interaction (like moving your mouse in your window), or direct OS interaction (like sending a signal from a finished timer that it kept track of).

With window management, events are sent to applications in the form of "messages". They're sets of data containing both an identifier for the message and information sent with it. In C/C++, this data are in structs. For every application, messages are collected in some form of queue, and it's the application's responsibility to access this queue to process the messages one by one (messages collected earlier are processed first). Each message is directed to a certain window within the application. So in a sense, "message-driven system" is a good synonym for "event-driven system".

Some notes on what I just mentioned above:

1. Window management on Winapi allows you to bypass this queue-like idea of "you have to process messages in the order they were received" and to send messages directly to windows in your application (with the SendMessage function). But in general, the event-driven system is based on sending messages to a message queue that the application processes.

2. From what I'm reading on msdn, some messages don't have to be specific to a given window, just specific to an application (in other words, messages are just specific to the thread running the application and don't specify a specific window within the application [instead, they specify NULL in C/C++ as a window]). I'm not sure of this, and I don't have experience with this. But still, the general idea is that messages are intended for windows within an application.

So, using Windows API can be thought of like:
  -You have an application (.exe) running.
  -This application can have:
    -no windows (maybe you just wanted to make a non-GUI, file renaming program for example)
    -one or more GUI windows
  -In the case that a Winapi application has windows, it will have interaction with the event-driven system.

One way to think of this is to think of a robot mail-management service in a programming business. This particular robot would receive mail one by one via a conveyor belt, and send it off to either the manager or the programmers that work under the manager. I made a diagram below:



 The programming business as a whole contains the mail robot and the business staff, like a Windows application as a whole contains its own message queue and windows. And like business staff, there's a sort of hierarchical relationship between a parent window and its child windows.

The "one-way" functionality of the conveyor belt is representative of the "you have to process messages in the order they were received" idea in a message queue (also known as "FIFO", "first-in, first-out". The -first- message -in- should also be the -first- message taken -out- by the application for processing).

The mail symbolizes messages. Mail can be specified to a particular staff member in a business and have certain information associated with it. And different letters of mail can contain different information (or even the same information, like the repeating electricity bill to Manager Suke in the diagram). In Windows apps, messages are addressed to specific windows in an application. They may be the same message (like notification that the user would like to try to close the app). Or they may differ entirely (messages may indicate typing in one time, but then a left mouse click right after).

I think the robot running the conveyor of mail is the most critical part. It symbolizes the application's actual interaction with the messages in the message queue. The robot is the one that actually looks for the mail in the conveyor belt, and is the one that also actually delivers it to business staff. Without it, the staff wouldn't receive their mail, and the business would fall apart.

But as a robot needs to be explicitly given instructions as to how to process the mail (it doesn't have a mind of its own), the source code in a Windows application needs to explicitly call the functions necessary to interact with the application's message queue. There are two major interactions:

1. Actually fetching the messages from the message queue (telling the robot to get the mail from the conveyor belt) is normally done in Winapi with GetMessage and PostMessage.

2. Then actually sending these messages to windows as needed (telling the robot to actually send the mail to the staff). This is done with DispatchMessage.

 I can refine the diagram analogy a bit to look like this, to reflect the robot's roles:



In code, you'll see this process of fetching and dispatching messages from the message queue in the form of a while loop. One form of this while loop is like so: (this is in the one_window and mult_windows VS projects)

MSG Msg;

while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

Without talking about the specifics of that "> 0" condition, GetMessage vs. PeekMessage, and DispatchMessage, I can say this:

-There's no complicated multi-threading or stuff like that required by you to access the message queue. The main responsibility for you in the source code is using the right functions.

-The "while" loop itself above is what makes an application continue to run. As opposed to a for loop, a "while" loop is more intended for things that run more indefinitely. All GUI applications use this "while loop" idea in tandem with the event-driven system to keep windows up as long as you want them too. In this situation, as long as the system doesn't send a message telling the application to break out of this "while loop" (like an indication to close the window or a system failure), the while loop (and therefore your application) will keep running. It's therefore standard for all Winapi GUI apps to have what's called a "message loop".

Nonetheless, a "while" loop is not required to actually use Winapi functions like GetMessage, PostMessage, etc. You can use them however you want, in a for loop, as a single function call, etc. Not using these functions in a loop won't break your program.

I guess I wanted to bring this up because in the glfwPollEvents designed specifically for GLFW, you'll see GetMessage and PostMessage used in a while loop with different code (I'll talk more later about what I found about glfwPollEvents). In different applications, you'll probably see different types of while loops, or a while loop may not even be used with these functions at all.

-But continuing from the last paragraph, to make another point, what's critical is that in a Winapi GUI application, you must interact with the message queue in your source code, or else it won't work.

If you don't attempt to examine/ fetch messages from the message queue, the Windows OS will not get any chance at all to interact with your window (even if there are no messages available), and your program will freeze.

I made a "one_window_no_fetch" project as an example. I changed the standard "message" loop to just a while loop that last 20 seconds, like below:

/*
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}*/

time_t current_time = time(NULL);
time_t time_limit = static_cast<time_t>(20);
while ((time(NULL) - current_time) < time_limit) {
//do nothing
}

If you try to run the program, and hover over your window, you'll see your mouse just turn into a wait icon. If you try to close the window with the red X button, you should see a "not responding" message appear.

The documentation for GetMessage (and PeekMessage too) also emphasizes that the function allows the OS to process important "internal events" involving the windows. Here's a quote:

"During this call...the system may also process internal events. If no filter is specified, messages are processed in the following order:

Sent messages
Posted messages
Input (hardware) messages and system internal events
...."

Another way to break your Windows application's message queue interaction is to not actually dispatch/deliver the messages you got from the message queue to their corresponding windows. I made a "one_window_no_deliver" project to show this. The message loop is still the same, just with the DispatchMessage call commented out:

while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
//DispatchMessage(&Msg);
}

(To say it now, if you run this program, you won't be able to close it normally. You must use Task Manager to kill it.)

If you run this, you'll notice that when you hover your mouse over the window, you won't get that wait icon. While your program does seem to work, you can't actually close the window (Alt + F4 won't work either). As I wrote above in bold, you need to use Task Manager to kill the application.

This error reflects that the OS has a chance to run process internal events with your window during the GetMessage message-fetching process (like really internal events, such as just keeping the window running and not crashing in the first place). However, it also shows that if the windows don't actually have a chance to receive the messages, they won't have any information to work with and won't know how to respond to even simple actions like mouse movement or a window close request.

To relate these two errors to the mail robot analogy, consider that as a robot doesn't have a mind of its own, you need to always tell it to do what you want, or else it won't do it.

If you don't tell it to look and fetch for new mail, it won't do it. And as a consequence, there's no point to try to have it deliver mail. It has nothing to deliver. Your business staff won't get the mail they need. Your robot's not working. Your business mailbox is probably getting too much mail and getting messed up. So as a result, your --entire-- business gets destroyed. This is sort of related to not fetching messages from the message queue with GetMessage. Without it, your GUI program will crash. I guess adding a bunch of X's to the diagram picture is a way to visualize this. Like, one X on the fetching part causes everything else to fail/"deserve an X" too.


If in the case that you do tell the robot to fetch the mail, but you don't actually tell the robot to deliver the mail to the staff, then the business still won't work. Manager Suke won't be able to pay off the monthly electricity bill if he doesn't actually get the letter that says how much the bill is.  And Programmer Carwa can't attend to the bug report if she doesn't actually get the report mail addressed to her. In a sense, part of the business is actually functional, but so much of it isn't functional that it's ultimately not working.

This is similar to using GetMessage in the message loop to access the message queue but not actually using DispatchMessage to route the messages to the proper windows (in the diagram, DispatchMessage would be routing the mail to the proper staff members). In the diagram, I'd think of putting check marks with the robot, but putting X's with the robot's task to deliver the mail, and with the staff themselves. The lack of check marks can be a good indication of how the business in this diagram is not functioning well.


-One last thing I want to point out here is that it does seem error prone to have separate functions for fetching messages from the message queue and actually delivering them to the windows. It does sound feasible to have function to handle all of this (maybe it could be called ManageMessage or RerouteMessage? Just an idea).

But this separation allows more flexibility. It allows you to write code that analyzes, reacts, and possibly changes messages from the message queue before dispatching them to the window. And it therefore offers more flexibility in writing the message loop for your application. The way you wrote your while loop in the code you posted is an example of this. (I'll plan to talk more about this later, in my notes on glfwPollEvents.)

With that, I think I've written enough of a high-level overview on Winapi's event-driven system. I tried to write it in a way such that you didn't have to know specific Winapi code. In the end, the best way to actually understand this is to actually do Winapi programming yourself. But still, hopefully the business analogy helped in the overview, as my bigger intention is to answer your GLFW questions.

At the very least, in my opinion, to understand the glfwPollEvents code, you can remember this:

1. In a Winapi GUI application, the event-driven system is required.

2. To use the event-driven system, you need to do both of these:
        a. use GetMessage/PostMessage to fetch messages from the message queue.
        b. use DispatchMessage to deliver messages to the windows.

Callbacks and their Relevance to Winapi

The last background information I want to talk about is about callbacks and their relevance in the Windows API. It gives insight into GLFW's glfwSetFramebufferSizeCallback function.

A callback is a function passed into another function with the intention to be called later. It's more of a naming convention. There's no "callback" keyword or something like that in C/C++.

Based on what you wrote in your forum question, I think you're not aware that functions are actually variables. I think a way to clarify this is to say that the function names in your function definitions actually represent pointers to executable code. The syntax in C/C++ allows me to show this explicitly. Given a function "test_function" that takes two ints and returns nothing, you can actually call the function in two ways:

(in my function_pointer_syntax project)

...
test_function(1, 2);

(*test_function)(1, 2);
...

The second way looks weird at first. The C++ operator precedence rules do give insight into this. But what I wanted to emphasize in the second way is that it reflects how function names are actually pointers in memory and that, like any pointer, you dereference the function name before making the actual function call. In my opinion, a line like "test_function(1,2)" is actually a shortcut for the more explicit "(*test_function)(1,2)". Nonetheless, "test_function(1,2)" is way more convenient to type and is more readable.

You can also actually print the memory address that a function name as a pointer represents too. See the function_address_printing project.

The idea of functions as variables being pointers still follows the general pointer idea. Any variable, like an int or a char, has two things:
  1. actual data
  2. an associated memory address

In a sense, even a pointer variable follows this idea. The variable itself is #2 from the list above, the memory address, and you dereference it to access the actual data (item #1).

And with a function variable, you can consider the variable as a pointer, and this pointer, when dereferenced, gives you access to the actual function itself (which you make use in a function call).

Even if functions are declared in global scope, they are still variables, and they can still be (and are) pointers. With the following snippet:

int return_two() {
  return 2;
}

const int some_var = 3;

int main(int argc, char** args) {
  ...
}

Even if some_var is in global scope, it's still a variable. It's scope doesn't change that. The same idea applies to the "return_two" (and even the "main") functions. Even if they're functions, and even if they're global, they're still variables. And as variables, they are reasonably defined by C/C++ to be pointers. I admit you didn't mention anything about confusion with scope, but I think pointing this out helps emphasize the idea even more that function variables/names are pointers.

Overall, what I wanted to emphasize here is this idea:

When you see a line like this in your code:

void function() {
  ...
}

You should see this function definition as:
  1. "function" is a variable. Even with all the syntax, it's still a variable.
  2. A variable can be a pointer. "function" as a variable is a pointer to executable code.

This confused me a lot when I first encountered this. And I think while normal function call syntax like "function(1,2)" is very convenient, it doesn't represent the idea of "a function is a pointer variable" like "(*function)(1,2)" does. And for me at least, I've rarely seen the more explicit version. I've never used it legitimately, and I don't think I've seen that in actual code. So I thought I'd put a lot of detail into pointing this out before continuing to discuss callbacks.

So anyways, going back to callbacks, what I wanted to bring from my function notes is this connection:

A function variable is a pointer. A pointer can be passed into a function. So it's reasonable to pass a function as an argument into another function.

Mainly, it looks odd at first, but it's still general C/C++, nothing special implemented by APIs for example.

With the the above connection, you can pass a function "Function A" into another function "Function B" for various reasons. Maybe you want to call "Function A" inside "Function B". Maybe you intend to have "Function B" store "Function A" as a global variable.

Nonetheless, the key thing here is that, in this example, "Function A" is a callback. It is a function that you passed into another function to be called later. It may be called by Function B or stored in a global variable. But the key thing that makes this a callback is that you didn't call it directly/immediately.

I guess it's called a "callback" because of that "not immediate" reason. With a callback, you don't intend to call it now. You intend to --call it back-- later through the means of passing it to another function.

A callback is still a function. The actual syntax to allow a define a function to take a callback as an argument is a little strange. I can't explain it all myself. But what I can say is that, as a function is still a variable, it follows the same idea that, in a function definition, for any parameter, you need to define some sort of type with it, and only certain variables can be assigned to this parameter.

Function-wise, this would mean that, in a function definition, a parameter that takes a callback would have to be specific enough about the callback's own --parameters-- and --return type--.

(Note: technically, I just found out, the "calling convention" is important too. I do mention that later. But as that's an optional thing to define [there's a default calling convention provided], the more critical thing is the --parameters-- and --return type-- still.)

I made a callback_usage project to demonstrate callback examples. In that project, I also show:

-how you can use typedefs (just like other types) to make function definitions with callbacks more readable.
-that while callbacks passed in must match the expected parameters and return type from the function definition, a callback's own parameters can be named whatever you want ("yes_function" and "no_function" have different parameter names in the project example)
-that you can still call a function with the same 2 ways that I mentioned previously ("callback_function" and "typedef_callbackf" use different ways)

While I'm not able to explain the actual syntax behind callback parameter definitions in C/C++, I can provide a visual that shows that how callbacks work in function definitions is still the same as other types:



I also found this called "Reading C type declarations", by Steve Friedl. It has an example with a function that reflects how the syntax involved with callbacks and functions involves operator precedence.

With the callbacks, the next thing I want to mention is how callbacks are used to customize Winapi Window procedures. In Winapi, internally, every window has a default procedure to handle the messages that are dispatched to it.

(Note: A procedure is just another word for "function". It appears in Winapi documentation when dealing with how windows handle messages, so to be formal, I just use that. In a general sense, "procedure", "callback", and "function" all mean the same thing. Maybe they technically vary in when they are used or what programming language they're considered in, but there's no critical difference, in my opinion.)

So to repeat, every window has a default procedure/function ("a default way") to handle messages sent to it. With the mail robot analogy, consider that each staff member (each window) has a default/standard way to handle things. When Manager Suke receives the electricity bill mail for example, it's intuitive for him to make sure to pay it.

In Winapi, internally, many windows probably have the same default procedure. For example, both Programmers Bormine and Carwa would likely both handle the bug report mail the same. They'd formally log the bug report, and attend to it soon. And maybe if the business got a letter about a monthly reminder to water a special plant in the office (maybe the plant's so special it has mail service), everybody (Manager Suke, Programmer Bormine, and Programmer Carwa) would go ahead and water the plant the same.

Regardless of what the default procedure is, everybody has their own "default" way of handling things. With Winapi, all windows have a default procedure.

I'll add to the business diagram visuals of "standard procedure" for Programmer Bormine, to reflect the "default procedure" idea.


Winapi allows you to customize a window's default window procedure (and to use this same "customization" in other windows) through the use of what are called window classes. In the one_window project, you'll see in the WinMain function:
  -a class registration
  -the creation of a window
  -the message loop

The class registration is of interest here. Without going into details, I want to point out a specific snippet:

WNDCLASSEX wc;
...
wc.lpfnWndProc = WndProc;

That assignment reflects how you can assign your own callback to be used later in a window that uses a specific class.

("WndProc" can be called a procedure, if you want to be formal. You can still call it a callback too. In that assignment line, it's not like you're passing "WndProc" to another function directly, but you do have the intention here of having the window use/call it later. That's good enough to call it a callback.)

"WndProc" is defined in main.cpp. One thing I want to point out is that in the function definition, "CALLBACK" is --not-- a keyword or anything intended with making the function so special that you can't call it directly and you have to pass it to another function for example.

As hinted by VS 2015, it's a preprocessor macro defined by Winapi to replace a calling convention called "__stdcall". Hover over the word in VS, or "right-click"->"Go To Definition" to see it explicitly #define'd in some minwindef.h header file.

I don't know exactly what a calling convention is, but looking at the source, and glancing at this site, I'm guessing:
  1. A calling convention is something you can use to explicitly define how the compiler translates your C/C++ source into assembly (and then ultimately to machine code in an .exe that you can analyze in a Hex Editor like Notepad++). I guess this can be important with optimization. I've never done Assembly, though.
  2. Apparently, you define a calling convention in a function after the return type and before the function name.

Whatever the details are, I just wanted to point out that the "CALLBACK"  macro is not a keyword.

However, it does represent a calling convention. And and I've just learned by testing, that a function's calling convention is important in determining in whether it can be passed as a callback to a certain parameter. It's just that you see it omitted so often that it does feel like, in my opinion, that it's not that critical of a detail.

To keep it brief, as I don't think this is critical to main Winapi discussion, I want to point out the assignment line that I mentioned above:

"wc.lpfnWndProc = WndProc;"

The lpfnWndProc member variable expects a callback of type WNDPROC. WNDPROC is defined in WinUser.h to be a callback specifically with the __stdcall calling convention. If you go back and remove the "CALLBACK" macro (and therefore the __stdcall convention) from the WndProc definiton, you'll get a compilation error.

Apparently, by default (by looking at the compilation error in VS), the compiler assigns a calling convention call __cdecl to WndProc. And with this calling convention, by C/C++ rules, WndProc can't be assigned to wc.lpfnWndProc.

That's the summary of the "CALLBACK" macro, code-wise.

Anyways, back to WndProc itself. To repeat, in the one_window project, it's a callback intended to customize the default window procedure. 

As I talked about with the callback_usage project, something has to pass arguments into WndProc to actually make it useful. In my callback_usage project, I passed arguments myself. In Winapi, arguments are passed by internal code hidden from you. (Windows API is not open-source, and as whoever developed this did this probably back around the 90s, when it was way harder to program, they have the right to keep stuff like that closed source.)

Regarding the definition parameters behind WndProc, I can say this:

If you analyze the MSG struct documentation that represents a Winapi message, you'll notice that it has all the parameters that WndProc defines. This hints that, as a message is passed to a window procedure (default or custom, doesn't matter), specific data is extracted from the message and passed into a window procedure for your convenience. In the business analogy, this sort of reflects the process of opening the mail the laying out its contents before analyzing them.

With the actual parameters, I can say this:

HWND hwnd: reflects the window itself (like the actual recipient of a letter)
UINT msg: reflects the main message (Like the body of the letter)
WPARAM wParam: reflects one specific detail regarding the main message (Like a specific sentence in the letter)
LPARAM lParam: reflects another specific detail regarding the main message (Like another specific sentence in the letter)

So without going into the function definition itself, and to generalize my discussion on callbacks and window procedures, here's what I want to point out:

1. You can define your own callbacks in Winapi to customize the window procedures that windows use to process the messages sent to them.
2. The definitions from window procedures you define reflect how you can receive various messages with various data to allow for flexible processing. 

Going back to the business analogy, it's like knowing that Programmer Bormine has his own, default way of handling a writeup request (a window always has a default procedure), but as part of the business, he is required to include his business's logo in his writeups. (You can provide a custom window procedure to augment or replace the default window procedure's functionality.)

I can add a little colored text to symbolize how the business requires Bormine to do just a little more than his usual write-up routine by adding the business's logo.



Hopefully, this'll make my notes on glfwSetFramebufferSizeCallback and the WM_SIZE message I mentioned a while back clearer.

My actual GLFW response

I feel like I've written enough background to help better understand my notes on glfwPollEvents. While most of my notes are guesses, I assume you've never tried the Windows API that GLFW abstracts, so I thought the background would still be worth it.

Anyways, I'll finally write my actual response to your questions on GLFW. I'll base it off of the prompt I gave myself. At this point, I'm going to assume:

1. You're familiar with Winapi's event-driven system.
2. You're familiar with callbacks and the window procedures involved with Winapi window management.

I provided my own explanation of these, for convenience. If you want to know more about Winapi, you'll have to look on your own. I'll be more concise about Winapi from now on.

glfwPollEvents and your processInput function

I'll start with the first question in my own prompt:

"Why is glfwPollEvents needed? You thought processInput makes this unnecessary."

I just came up with the idea to run your source under the debugger in Visual Studio. My original idea was to analyze the github source, but as I built the open-source GLFW libraries myself, I can access them in VS during debugging. So I'll base my comments off of that while I write this.

I stepped into the glfwPollEvents in your code. This gave me the following snippet in window.c (line 866)

GLFWAPI void glfwPollEvents(void)
{
    _GLFW_REQUIRE_INIT();
    _glfwPlatformPollEvents();
}

There's _glfwPlatformPollEvents(), which is the actual PollEvents call. I step into it, and I'm led to a _glfwPlatformPollEvents on win32_window.c. (line 1350)

It looks like the function is structured like so:

1. Query the message loop and dispatch messages as needed.
2. Manage something special with the Shift Keys.
3. Do some special check with the cursor.

The key thing is the first item, reflected in this snippet:

void _glfwPlatformPollEvents(void)
{
    while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {
            // Treat WM_QUIT as a close on all windows
            // While GLFW does not itself post WM_QUIT, other processes may post
            // it to this one, for example Task Manager

            window = _glfw.windowListHead;
            while (window)
            {
                _glfwInputWindowCloseRequest(window);
                window = window->next;
            }
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }
...

From this, I'm seeing that, on Windows, glfwPollEvents does the necessary querying and dispatching of messages from the message loop that Winapi is built on. Without this, the message loop is never accessed, the OS never gets to do important internal operations with the window, and the program will crash. (You can see this by commenting out glfwPollEvents).

So glfwPollEvents is the most important function in managing an active window. All other functions are based on the data gotten from the message loop that glfwPollEvents accesses. So far, without looking at the source, I'm guessing the glfwGetKey call in your processInput function depends on glfwPollEvents. But your processInput --definitely does not-- replace it.

Another thing I thought may be interesting is how glfwPollEvents() doesn't have any parameters. At first, you may think that as one of its functions is to keep a window running, it should take some window argument. But as the message loop on Winapi doesn't depend on a window argument (since the loop can be designed for multiple windows), glfwPollEvents doesn't depend on it either.

This is also a good time to point out how the separation of querying and dispatching in the message loop I mentioned earlier allows for flexible message loop implementations. In this case, whoever wrote this decided to process a message like WM_QUIT in the message loop instead of just leaving it to the window procedures. Maybe the reason behind that has to do with cross-platform design? Just guessing there.

More About your processInput function

The next thing in my prompt is this:

"I mentioned glfwGetKey and glfwSetWindowShouldClose in my initial reply. How does that help with insights on your processInput function?
  -How is the Esc key related to glfwPollEvents and your processInput function?"

I think with glfwPollEvents, GLFW somehow uses the messages from the Winapi message loop to update some "_GLFWwindow" struct that GLFW itself defines that represents data for a window.

With an updated "_GLFWwindow" struct window, you can pass it to glfwGetKey (which you do in your processInput function), which then accesses that struct to query the status of a certain key. (For example, like in processInput, you can query the Esc key's status.)

Using VS, I was able to find the definition of _GLFWwindow in "internal.h", in line 345:

struct _GLFWwindow
{
    struct _GLFWwindow* next;

    // Window settings and state
    GLFWbool            resizable;
    GLFWbool            decorated;
    GLFWbool            autoIconify;
    GLFWbool            floating;
    GLFWbool            closed;
    void*               userPointer;
    GLFWvidmode         videoMode;
    _GLFWmonitor*       monitor;
    _GLFWcursor*        cursor;

    int                 minwidth, minheight;
    int                 maxwidth, maxheight;
    int                 numer, denom;

    GLFWbool            stickyKeys;
    GLFWbool            stickyMouseButtons;
    int                 cursorMode;
    char                mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
    char                keys[GLFW_KEY_LAST + 1];
    // Virtual cursor position when cursor is disabled
    double              virtualCursorPosX, virtualCursorPosY;

    _GLFWcontext        context;

    struct {
        GLFWwindowposfun        pos;
        GLFWwindowsizefun       size;
        GLFWwindowclosefun      close;
        GLFWwindowrefreshfun    refresh;
        GLFWwindowfocusfun      focus;
        GLFWwindowiconifyfun    iconify;
        GLFWframebuffersizefun  fbsize;
        GLFWmousebuttonfun      mouseButton;
        GLFWcursorposfun        cursorPos;
        GLFWcursorenterfun      cursorEnter;
        GLFWscrollfun           scroll;
        GLFWkeyfun              key;
        GLFWcharfun             character;
        GLFWcharmodsfun         charmods;
        GLFWdropfun             drop;
    } callbacks;

    // This is defined in the window API's platform.h
    _GLFW_PLATFORM_WINDOW_STATE;
};

If I step into glfwGetKey in the debugger, I see its definition in input.c, in line 259. I see several lines of the form "window->keys[key]". This even includes the return statement: "return (int) window->keys[key];". This reflects the "querying" idea that glfwGetKey does, specifically involving the "keys" array defined in the _GLFWwindow struct.

So I can say glfwGetKey is highly dependent on glfwPollEvents. I don't really know how glfwPollEvents actually updates a _GLFWwindow struct. I can't find a window procedure reflecting this, or just plain code. But I'm pretty sure it's like this.

I think "glfwSetWindowShouldClose" is actually not really related to glfwPollEvents at all. Looking at the source (window.c, line 424), the main part is some assignment to a _GLFWwindow struct:

window->closed = value;

There isn't any interaction with the message loop at all (and therefore glfwPollEvents).

However, what I find really neat is that glfwWindowShouldClose, the function you call in your source while loop, just queries what's set by glfwSetWindowShouldClose. You can see that's it's mostly a return statement in the source (window.c, line 409):

return window->closed;

This is actually just above the glfwSetWindowShouldClose definition too.

So to put it all together, what I'm seeing is:

1. Your processInput function (and therefore querying the Esc key's status) depends on glfwPollEvents.
2. Specifically glfwGetKey is dependent on the data glfwPollEvents gets from the message loop.
3. glfwSetWindowShouldClose isn't really related. It's more of just a struct member assignment. (But it is complimented with glfwWindowShouldClose)

However glfwPollEvents actually updates a _GLFWwindow struct, I think it can still be related to the business analogy I made in this post. In this case, normally you use just one window in GLFW, so I'll consider a programming business with just one person, Manager Suke.

While I can't find any GLFW source defining a custom callback for a Winapi window, I'm still sure that a GLFW window must have at least a default procedure. So I can still visualize Manager Suke with a "standard procedure" for everyday things, like I did with Programmer Bormine. This is what I'll provide for now:





Working from this diagram, I'd first say that the _GLFWwindow struct design idea is like: "put data from the message loop in a struct, and access data there instead of from the message loop directly". In relation to the business analogy, it's like having an archive of electronic copies of your mail up to the last week (you access a struct instead of use the window procedure directly). You still get the original mail and can still open it (you can still use the window procedure directly in this design.), but you now have the convenience of having your recent mail kept away somewhere too, if you want too.

In the business analogy, you could consider your mail robot putting copies of your most recent mail in an archive shelf, and then sending the original mail to you:



===
The last set of questions from my prompt are:

"How does glfwSetFramebufferSizeCallback work? How are arguments passed to the width and height parameters of the callback function?
  -How do you know to set up your framebuffer_size_callback function as you did for glfwSetFramebufferSizeCallback?
  -I mentioned the WM_SIZE message in my reply. How does this give insights into the glfwSetFramebufferSizeCallback function?"

Source-code wise, glfwSetFramebufferSizeCallback is just like glfwSetWindowShouldClose. You're just now setting some callback member in the _GLFWwindow struct you pass to glfwSetFramebufferSizeCallback.

Apparently, this specific source (window.c, line 855) also uses some special macro to do some reassigning (if you look at the _GLFW_SWAP_POINTERS macro definition, the "swapping" is reassinging) in a way such that you can get the previously assigned callback assigned to your window:

GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
                                                              GLFWframebuffersizefun cbfun)
{
    _GLFWwindow* window = (_GLFWwindow*) handle;
    assert(window != NULL);

    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
    return cbfun;
}

This return design is more of the GLFW dev's choice, in my opinion.

To know how to structure your callback, check the documentation for glfwSetFramebufferSizeCallback. It's also shown in the source as in above that you need to pass a callback that's the same as the one specified by the "GLFWframebuffersizefun" callback type. But documentation is always easier to read:

    typedef void(* GLFWwindowsizefun) (GLFWwindow *, int, int)

The last two major questions I have left in my prompt are then:

-How are arguments passed to the width and height parameters of the callback function?
-I mentioned the WM_SIZE message in my reply. How does this give insights into the glfwSetFramebufferSizeCallback function?

As I mentioned earlier, glfwSetFramebufferSizeCallback is essentially just a --setting/assigning-- function. So the real focus now to answer these last two questions is to look at how the assigned callback is used.

I can't find specific source, but my best guess is that GLFW's abstraction of Winapi does include a custom procedure for its window. This custom procedure probably has it such that if the WM_SIZE message is received, GLFW extracts the window's new client width and height, whitch are the dimensions of the "inside of the window", the area without the frame. (Your OpenGL rendering context area and a function like glViewport are only concerned with the client area, not the dimensions of the surrounding window frame. Also, what's not the client area is called the nonclient area in Winapi, just a fun fact.)

And then with this, GLFW passes it to its own callback function. set by glfwSetFramebufferSizeCallback (only if it's not NULL. If you didn't set any callback in the first place, there's no sense in passing the data then.) (

And then with the extracted width and height data, GLFW then passes it to the callback function

In pseudocode, maybe GLFW has a custom window procedure that looks like this:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        switch (msg) {     
                case WM_SIZE:
                        <get client area width and height>.
                        <pass these to GLFW's own callback, if there is any>

...
        }
...
}

I made a resize_callback_idea project to implement this pseudocode idea in Winapi, using my own callback definitions. It should make it easier to understand the pseudocode. The program asks if you want to set a predefined callback. If you click "Yes", when you resize the window, you'll get text about the window's new height and width. And If you click "No", you'll get "No callback available" for text.

Nonetheless, it's still just an idea. I don't have any code to show that GLFW actually does something like this, but I do feel like it would.

So to sum it up, my answers to the lasts question of my prompt are:

1. glfwSetFramebufferSizeCallback by itself sets a callback member variable in a _GLFWwindow struct you pass to it.
2. Check the documentation to know what callback to pass to glfwSetFramebufferSizeCallback.
3. The actual size callback is called when the window is resized. GLFW passes the window's client areas dimensions to this callback. How this is done, I'm not sure. I think GLFW does define it's own Winapi custom procedure to do this.

In the business analogy, if in the case GLFW's size callback is called directly in a custom procedure, then I can complete the entire analogy by adding "colored text" with Manager Suke (just like I did with Programmer Bormine in a previous diagram) to represent "custom/extra procedure" Suke has to do as part of running his business:




End of Response: Final Thoughts

And that's my entire response. Hopefully it helps. This took many days to write, but as I intend to make responses like these public, I do put honest consideration into them. It'd be cool to reference this again if someone asks a question like this. And it does help me too (for example, I didn't know that a calling convention was important in passing a callback to another function. Got to learn something new).

For this particular response, I assumed you weren't familiar with Winapi, as you were mainly asking about GLFW. Also, this response was intended for the OpenGL forums. So I thought it'd be appropriate and worth it to go into detail into Winapi. And as Winapi isn't covered so much online outside of msdn, I thought I'd add my own notes to it.

Maybe my mail robot business analogy will get popular one day? That'd be neat. Put some thought into that one. I don't know when I came up with that, but I enjoyed developing it throughout this response. Anyways, just wanted to say that for the record, if it does get popular. : )

Other things

The rest of what I write concerns why I think you should do Windows API as a programmer, some Winapi sources, and credits to the images I used in my diagrams.

Why I think you should learn Windows API

As part of a post-write, I want to say that I think it's worth it to look into the Windows API as a programmer. I haven't written any huge apps on Winapi, but from a learning perspective, I can vouch that this is really worth the effort.

The list of reasons I came up with are below:

1. Windows API is gigantic, but it gives you maximum flexibility and control over Windows apps. If you're goal is a less demanding project like making a 2D program about drawing lines, then using an abstraction API like the cross-platform Tkinter GUI API on Python is better. But if you're going for something more intensive like a 3D application, then something like OpenGL on Winapi is a great idea. Not cross-platform, but worth the control.

2. Windows API gives you low-level access to not just OpenGL on Windows, but other graphics APIs like GDI and DirectX. And non-graphics APIs too, like networking, sound, and telephone programming (I've never done those, just know they're available).

3. It does take a while to understand it (and there's still OpenGL too), but Winapi concepts transfer nicely to abstraction APIs like Qt and GLFW.

GLFW especially, as it's open-source. I was able to look at the source code to look into the GLFW questions you mentioned, and got to see actual Winapi calls in glfwPollEvents. That's as explicit of a connection as you can make between two APIs, really nice to see.

Qt is closed-source, but given its intended scope (cross-platform, beyond graphics, embedded systems), it's fair for the developers to keep it like that. That sounds really hard to do.

In a sense, Winapi allows you to get a view of "where it all started" for cross-platform GUI APIs that intend to include Windows. And I think that's really worth it.

4. You get to see the relevance of specifications in the OpenGL Registry involving OpenGL on Winapi. (These specifications are prefixed with "WGL", like WGL_ARB_pixel_format and WGL_ARB_create_context.)

Like the OpenGL specification, I think these are hard to read too (but there's no need to read them completely). However, it's nice to see the offical source from where a tutorial like "Creating an OpenGL Context (WGL)" on the OpenGL Wiki gets functions like "wglCreateContextAttribsARB" from.

5. At this low-level of programming, you can consider trying to compile a Winapi program from the command-line (like, actually invoke a .exe compiler program, type in your source, and link relevant libraries). With IDE's like VS 2015 now, in practice, it's still way easier and convenient to just press a button to do compilation, but I think it's an insightful experience to actually compile a GUI application using just command line options.

I mean, with a compiler, you can compile console programs too, but I think it's more exciting to try to compile a sort of "Hello World"-like GUI app with bare minimum tools. Again, it's not practical, it just feels neat to do so (as it probably was the norm before the 2000s).

6. Windows API is pretty cool.
  -You get appreciation of lower-level programming concepts, even if you're just learning it and not developing big apps.
  -It's neat to study an API that abstraction APIs like Qt and GLFW are based on.
  -And you may find historical computer fun facts. Like in the Programming Windows book I mention later, Petzold writes that "Ctrl + Z" for undo used to be "Alt + Backspace" as the standard. (It still works today too. Try it on Notepad or Word!)

If you decide to do Windows API, good luck on it. I actually first took it seriously after I made this post in the OpenGL forums asking for help about some "GL_STENCIL_BITS" value. It's been a while. I forgot all about the stencil buffer now, but it was cool to make the "minimal.c" file I mention in that post work.

(I also made another blog post around June, just to put it here, where I talk more about my confusion with GL_STENCIL_BITS. Looking back at it, I think I misinterpreted some function calls. Or maybe I switched my graphics card for some reason and made myself more confused. Not sure. At the time, I was still just interested in copy-pasting code from the LearnOpenGL tutorials and just seeing cool graphics on my screen, haha.)

Winapi is gigantic, but understanding window management in Winapi and the event-driven system is already really good, in my opinion. Definitely don't memorize functions here. Winapi's too big with that. But as Winapi's low-level, you'll benefit the most from understanding general concepts.

Windows API Sources

Here are Winapi sources that I've used this year, when learning Winapi:

1. msdn - Windows API Index

Link to general index describing all of Winapi's features.

I just noticed OpenGL is listed under "Deprecated or legacy APIs". But OpenGL is very powerful, definitely not worth to be called deprecated. I guess the developers want you to use DirectX instead, haha.

(To be fair, I think the real reason behind this is because the default OpenGL context creation functions provided by Winapi isn't actually all that there is. With approved specifications like WGL_ARB_pixel_format, graphics card vendors give you access to more flexible context creation functions. As the Winapi devs are likely aware of this, maybe by some certain design choice, they chose not to make those specifications standard in Winapi, and kept Winapi as it currently was. So Winapi's OpenGL functions by themselves are "deprecated"/"not upgraded", compared with the specifications.)

2. theForger's Win32 API Programming Tutorial, by Brook Miles

I think this is the best tutorial for newcomers to Winapi. It's what I used. Very friendly, and the author gives VS solutions to the example code. I'd say it's analogous to the LearnOpenGL tutorials for OpenGL.

Miles also provided a "References" page containing more Winapi sources.

3. Programming Windows, Fifth Edition, by Charles Petzold

I got this book as a hardcover from Amazon. I found it from the "References" page on theForger's tutorial I mentioned earlier. This is an amazingly detailed book. It's an excellent companion that adds more detail to the Winapi descriptions provided my msdn.

The book was published in 1998, according to Amazon (my hardcover says 1999, probably another version with some corrections). However, much of Winapi from back then is still used today, as Winapi is designed to make programs from back then still work today. The concepts are still relevant, and you can already make really powerful applications with them.

There is a 6th edition, but apparently Petzold wrote it for C# and something called XAML. But I think it's easier and more useful to learn Winapi in C/C++, as the 5th edition does. The msdn docs for Winapi are based on C/C++. And if you're an OpenGL programmer, the OpenGL documentation is designed around C too.

I definitely don't read the entire thing, and I wouldn't recommend that to you either. It's 1100 pages, reflective of Winapi itself. I just take the pages I need.

Also, I got a used hardcopy, but I still got a CD. That was nice of whoever decided to re-sell it. If you decide to get a paper book but don't get a CD, the book's source is available on Petzold's site.

4. The Waite Group Press's 3-book series on Win32.

This includes:
  1. Windows NT Win32 API Superbible
  2. Windows 95 Common Controls & Messages API Bible
  3. Windows 95 Multimedia & ODBC API Bible

This series is more of documentation books on Winapi in the 90s. They're essentially a list of functions with the authors' own descriptions of them (or possibly from an old version of Winapi documentation, by my guess).

So this set isn't really a learning book. To be honest, I found the first book in my university library. Then I got curious and bought the other two books.

I don't regularly look at these a lot. However, the book is organized into chapters, and the authors give useful summaries about the chapter's functions in the beginning of each chapter.

While I haven't really used the 2nd and 3rd book yet, I've found the first book handy as an extra reference to compare with Petzold's book and msdn when I'm trying to learn something new from Winapi.

Also, these books are old, so I thought I'd get myself more of these books while they're still available on Amazon.

So I wouldn't really recommend these as I haven't used them so much. Glancing at them, I can say they're good, but msdn's documentation (and Google in general) is more useful. Nonetheless, I can see how they'd be good as an extra reference from a past era.

What I can say here though is that if you get a paperback book with a CD, be careful with it! Take the CD out first. When I got the ODBC book, I began fanning it to look at the pages, but I bent the CD and broke it in half in the process. Here's a picture of it:


I tried to tape it back together out of some hope that that would make it work. By the time I tried using tape, when I peeled it off, I ruined the CD for good.

In retrospect, maybe superglue might've worked. I'd never know. I don't have the source anymore, but I'm okay with just the book content.

Anyways, be careful with CD's in a paperback.

General Sources

All sources I want to include here are in this dropbox folder. This includes the VS solution I used for this blog, and diagrams.

I based most of my Winapi code from theForger's "A Simple Window" tutorial.

I used draw.io for all my diagrams. I included the .xml you can load into draw.io, all the images I used, and a sources.txt to the images I got from the internet.