GLUT function key stop refreshing - opengl

I've used FreeGLUT 3.0.0 (built from source using MSVC 2013) under Windows 7 to create an OpenGL context for quite a while, but today I encountered some strange behavior: When I press the F10 key, the window stops to refresh. Following is the minimal code that will achieve this strange behavior under MSVC 2013, Windows 7:
#define FREEGLUT_STATIC
#include <gl/glut.h>
#include <iostream>
using namespace std;
void init()
{
glClearColor(1.0, 0.0, 0.0, 0.0);
}
void display()
{
cout << "a" << endl;
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
glutPostRedisplay();
}
void reshapeFunc(int width, int height)
{
glViewport(0, 0, 640, 480);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(0, 0);
glutCreateWindow("What?");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshapeFunc);
glutMainLoop();
return 0;
}
In this example, when I press F10, the command line stops to print the character 'a', and continues when I press F10 again.
The strange thing is that I didn't do anything special to F10 (I encountered this problem since the point I didn't write anything like GLUT_KEY_F10). All other function key don't have this problem. I don't why this is specific to the F10 key.
Does anyone have any suggestion about how to deal with this problem?

As suggested here:
F10 is the shortcut key to enter a windows' menu. It should be enough to not pass a valid HMENU handle. I haven't tested this though. You probably want to avoid using F10 if it doesn't work though.
If you insist, you can get F10 by catching WM_SYSKEYDOWN and NOT passing the message on to DefWindowProc.
Adding a flag to skip the DefWindowProc() call on SC_KEYMENU events to FreeGLUT's WM_SYSCOMMAND handler seems to "fix" the problem:
...
case WM_SYSCOMMAND : /* 0x0112 */
{
/* HACKITTY HACK HACK HACK */
int skipDefWindowProc = 0;
{
/*
* We have received a system command message. Try to act on it.
* The commands are passed in through the "wParam" parameter:
* The least significant digit seems to be which edge of the window
* is being used for a resize event:
* 4 3 5
* 1 2
* 7 6 8
* Congratulations and thanks to Richard Rauch for figuring this out..
*/
switch ( wParam & 0xfff0 )
{
case SC_SIZE :
break ;
case SC_MOVE :
break ;
case SC_MINIMIZE :
/* User has clicked on the "-" to minimize the window */
/* Turning off the visibility is handled in WM_SIZE handler */
break ;
case SC_MAXIMIZE :
break ;
case SC_NEXTWINDOW :
break ;
case SC_PREVWINDOW :
break ;
case SC_CLOSE :
/* Followed very closely by a WM_CLOSE message */
break ;
case SC_VSCROLL :
break ;
case SC_HSCROLL :
break ;
case SC_MOUSEMENU :
break ;
case SC_KEYMENU :
skipDefWindowProc = 1;
break ;
case SC_ARRANGE :
break ;
case SC_RESTORE :
break ;
case SC_TASKLIST :
break ;
case SC_SCREENSAVE :
break ;
case SC_HOTKEY :
break ;
#if(WINVER >= 0x0400)
case SC_DEFAULT :
break ;
case SC_MONITORPOWER :
break ;
case SC_CONTEXTHELP :
break ;
#endif /* WINVER >= 0x0400 */
default:
#if _DEBUG
fgWarning( "Unknown wParam type 0x%x", wParam );
#endif
break;
}
}
#endif /* !defined(_WIN32_WCE) */
/* We need to pass the message on to the operating system as well */
if( skipDefWindowProc == 0 )
{
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
}
break;
}
...

Related

Remove Windows Error/Beep sound when pressing Alt + Key combinations

I am trying to remove windows error sound from my Flutter (Win32) Application. After some research I came up with this fix. I tried this fix but it's not helping in my Flutter application.
Heres the code to handle WM_SYSCHAR message:
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept {
if (message == WM_SYSCHAR) {
std::cout << "SYSCHAR from win32" << std::endl;
return 0;
}
...
}
When I press the Alt+Space, "SYSCHAR from win32" is printed in the console. But whenever I press any other key with Alt, this is not printed and the Windows error sound is played. It seems like SYSCHAR message is handled somewhere else?
This can be used to know the working and initialization of Win32 App in Flutter.
I just want to tell the Application that Alt+Key combinations are handled and it doesn't have to play Windows error sound.
Thanks to #IInspectable for suggesting me to use keyboard accelerators.
The problem is Flutter's main loop doesn't have keyboard accelerators. So I followed how to use keyboard accelerators documentation and modified the main loop as follows:
Created accelerator table by calling CreateAcceleratorTable
LPACCEL accels = GenerateAccels();
HACCEL haccel = CreateAcceleratorTable(accels, 36);
if (haccel==NULL) {
return EXIT_FAILURE;
}
Here's the GenerateAccels function:
LPACCEL GenerateAccels() {
LPACCEL lpAccel = new ACCEL[36];
// Alt + Number combinations:
for (int i = 0; i < 10; i++) {
lpAccel[i].fVirt = FALT;
lpAccel[i].key = (WORD)(0x30 + i);
}
// Alt + Alphabet combinations (NOT WORKING AT THE MOMENT):
for (int i = 0; i < 26; i++) {
lpAccel[i + 10].fVirt = FALT;
lpAccel[i + 10].key = (WORD)(0x41 + i);
}
return lpAccel;
}
Then adding a call to TranslateAccelerator in the main loop
::MSG msg = { };
while (::GetMessage(&msg, nullptr, 0, 0) > 0) {
if (!TranslateAccelerator(msg.hwnd, haccel, &msg)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
I also added this check to prevent error sound from playing when any key is pressed after pressing Alt (Alt is not held down).
flutter_window.cpp
case WM_SYSCOMMAND:
// If the selection is in menu
// handle the key event
// This prevents the error/beep sound
if (wparam == SC_KEYMENU) {
return 0;
}
Note: One thing that isn't working is Alt + Alphabet combinations. When pressed, it is still playing that error sound. In my case it's not important right now, but if someone finds the fix then please share.

How to handle WM_ENDSESSION in a console app

I wrote a program to register mouse events, and I want it to terminate when the computer is shutdown (and then perform a flush and a final print).
I tried with a CtrlHandler, but it works only with Ctrl-C and not when the system is shutdown, because I am using a Win32 library, according to MSDN:
If a console application loads the gdi32.dll or user32.dll library, the HandlerRoutine function that you specify when you call SetConsoleCtrlHandler does not get called for the CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT events. The operating system recognizes processes that load gdi32.dll or user32.dll as Windows applications rather than console applications. This behavior also occurs for console applications that do not call functions in gdi32.dll or user32.dll directly, but do call functions such as Shell functions that do in turn call functions in gdi32.dll or user32.dll.
To receive events when a user signs out or the device shuts down in these circumstances, create a hidden window in your console application, and then handle the WM_QUERYENDSESSION and WM_ENDSESSION window messages that the hidden window receives. You can create a hidden window by calling the CreateWindowEx method with the dwExStyle parameter set to 0.
So, first I have to create a hidden window, and then I have to intercept the the WM_ENDSESSION message. But how?
I tried to read some examples, but I can't figure out how to do this.
Here is my code:
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
switch (fdwCtrlType)
{
// Handle the CTRL-C signal.
/*case CTRL_C_EVENT:
printf("Ctrl-C event\n\n");
Beep(750, 300);
return FALSE; //TRUE
// CTRL-CLOSE: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
Beep(600, 200);
printf("Ctrl-Close event\n\n");
return FALSE; //TRUE
// Pass other signals to the next handler.
case CTRL_BREAK_EVENT:
Beep(900, 200);
printf("Ctrl-Break event\n\n");
return FALSE;
*/case CTRL_LOGOFF_EVENT:
Beep(1000, 200);
printf("Ctrl-Logoff event\n\n");
myfile << "totale :" << tot;
myfile.flush();
myfile.close();
return TRUE; //FALSE
case CTRL_SHUTDOWN_EVENT:
Beep(750, 500);
printf("Ctrl-Shutdown event\n\n");
myfile << "totale :" << tot;
myfile.flush();
myfile.close();
return TRUE; //FALSE
default:
return FALSE;
}
}
int main(){
if (SetConsoleCtrlHandler(CtrlHandler, TRUE))
{
printf("\nThe Control Handler is installed.\n");
for(;;)
{
code that print the mouse event(........)
}
}
else
{
printf("\nERROR: Could not set control handler");
return 1;
}
return 0;
}
You can just create a hidden GUI window in console application and handle WM_ENDSESSION in the window procedure as shown below
#include <Windows.h>
HWND g_hidden_window = nullptr;
LRESULT CALLBACK wnd_proc(HWND, UINT, WPARAM, LPARAM);
// Main entry point of your app
int main() {
HMODULE current_instance = ::GetModuleHandle(L"");
// Register the window class
WNDCLASSEX window_class_ex = { 0 };
window_class_ex.cbSize = sizeof(WNDCLASSEX);
window_class_ex.lpfnWndProc = wnd_proc;
window_class_ex.lpszClassName = L"Foo";
window_class_ex.hInstance = current_instance;
if (!::RegisterClassEx(&window_class_ex)) {
return 1;
}
// Create an overlapped window
g_hidden_window = ::CreateWindow(
L"Foo",
L"",
WS_OVERLAPPED,
0, 0, 0, 0,
nullptr,
nullptr,
current_instance,
0);
if (!g_hidden_window) {
return 1;
}
MSG message;
// Main message loop
while (::GetMessage(&message, nullptr, 0, 0)) {
::DispatchMessage(&message);
}
}
Now, in your main window procedure, you should handle WM_ENDSESSION. In your case, I see no reason to handle WM_QUERYENDSESSION. You should also handle WM_CLOSE and/or WM_DESTROY to quit the main message loop:
// Main window procedure
LRESULT CALLBACK wnd_proc(HWND window_handle, UINT window_message, WPARAM wparam, LPARAM lparam) {
switch (window_message) {
case WM_ENDSESSION:
if(wparam) {
// According to MSDN this value will be 1 when the system is about to shut down: https://learn.microsoft.com/en-us/windows/win32/shutdown/wm-endsession
// Invoke your function here
CtrlHandler(CTRL_SHUTDOWN_EVENT);
}
break;
case WM_CLOSE:
DestroyWindow(window_handle);
break;
case WM_DESTROY:
::PostQuitMessage(0);
break;
default:
return ::DefWindowProc(window_handle, window_message, wparam, lparam);
}
return 0;
}
To gracefully shut down the app, you will have to break that message loop. To do so, you will have to send a WM_CLOSE message:
SendMessage(g_hidden_window, WM_CLOSE, 0, 0);
Or, explicitly destroy the window by calling:
DestroyWindow(g_hidden_window);
Let me know if it works. I have not tested it because I'm on a Mac right now, but it should work.

MessageBox() returning 0 when called from Win32 button press

I'm barely a week into Win32 GUI programming, so I'm confident/hopeful this is something simple. For your consideration, I've provided a sample of my code below.
As a quick brief, my application watches for another application to be open so that I can modify that application's memory. I've placed this initial check at the top of my UI looper as follows such that it will only run once (in which case the user can only cancel and the app closes, or execution resumes past the if statement with hWndApp having a value assigned):
if (!hWndApp) {
appCheck();
}
If I start my application and the other application isn't running, appCheck(); fires and the waterfall of execution therefrom acts accordingly: a message box appears (and will keep appearing if the user clicks "Retry") until the other application's window is found. If the user clicks "Cancel," the application exits and all is well. If they click "Retry" once the other application is running, then my application will finish painting to the screen and execution is normal.
The funny business starts the next time I call appCheck(); (which happens when one of either two buttons is clicked) if the other application has been opened, then closed.
While debugging (via Visual Studio 2017), the variable I assign the MessageBox() call to equals 0 when the other application has been opened, then closed, then the following:
Push button to call appCheck();
getProcessHandleAndPID(); is then called within the if statement because the window can't be found
AppCheckMessageBox(); is then called within the while loop because the window can't be found
The debugger then points to the first line inside of AppCheckMessageBox();, which is the entire int msgboxID = MessageBox(); bit
Pressing F11 (Step Into), no window shows and the application exists after the default choice in the switch statement is triggered since the value of msgboxID is 0 (indicating the MessageBox() call failed, so I tried calling GetLastError() before exit(EXIT_FAILURE), but to no avail).
I'm not sure where my error lies, but I've sought many solutions--none of which have panned out. Finally, if you see any variables below that look misnamed or undeclared, it's solely due to my modification of the code for this post to try to generalize/ shorten it. I may have left out some global variable declarations, etc.
Thank you for any help/guidance you can provide! I'm at my wit's end with this right now...lol.
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
void getProcessHandleAndPID()
{
hWndApp = FindWindow(NULL, _T("NameOfApplication"));
while (!hWndApp) {
AppCheckMessageBox();
}
//Much more code here
}
//---------------------------------
// Function to show message box /
//-------------------------------
int AppCheckMessageBox()
{
int msgboxID = MessageBox(
NULL, //I tried making this hWndApp as well, but no difference
(LPCWSTR)L"Cancel to exit or start the app and click Retry.",
(LPCWSTR)L"Application Not Found!",
MB_ICONSTOP | MB_RETRYCANCEL | MB_SYSTEMMODAL | MB_SETFOREGROUND
);
switch (msgboxID)
{
case IDCANCEL:
exit(EXIT_FAILURE);
case IDRETRY:
getProcessHandleAndPID();
break;
default:
//GetLastError();
exit(EXIT_FAILURE);
}
return msgboxID;
}
//------------------------------------------------
// Function to check if application is running /
//----------------------------------------------
void appCheck() {
if (!FindWindow(NULL, _T("NameOfApplication"))) {
getProcessHandleAndPID();
}
}
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!hWndApp) {
appCheck();
}
switch (message)
{
case WM_PAINT:
//Code here
break;
case WM_CREATE:
//Code here
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
if (LOWORD(wParam) == BTN_ENABLE) {
appCheck();
//Do stuff with button press
}
if (LOWORD(wParam) == BTN_DISABLE) {
appCheck();
//Do stuff with button press
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Not really an answer, but too long for comments:
This isn't your real code. Many things are missing, there are mismatched braces which would prevent compilation, etc. Always show your real code if you want help.
As David says, calling appCheck() every time you receive a message is the wrong approach. If you want to call it once after your window opens, do that before entering your message loop.
Your code is needlessly recursive (getProcessHandleAndPID() calls AppCheckMessageBox() which calls getProcessHandleAndPID() which calls...) and will potentially lead to a stack overflow.

Disable task switching keys with c++

I've done a lot of searching around with no real solution (to my own problem) so I thought I'd ask here.
I'm designing a kiosk-like program that prevents the user from using task keys (alt+tab, alt+esc, ctrl+esc, etc) while the program is running. Note I'm a novice programmer thus I'd want to stay away from separate dll handling if I can. Particularly, I have went to this site http://support.microsoft.com/kb/226359/en-us for the code. A simplified part of my code looks like this at the top:
HHOOK mule;
HHOOK g_hKeyboardHook;
BOOL g_bFullscreen;
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{
// By returning a non-zero value from the hook procedure, the
// message does not get passed to the target window
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
BOOL bControlKeyDown = 0;
switch (nCode)
{
case HC_ACTION:
{
// Check to see if the CTRL key is pressed
bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
// Disable CTRL+ESC
if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
return 1;
// Disable ALT+TAB
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
// Disable ALT+ESC
if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
break;
}
default:
break;
}
return CallNextHookEx (mule, nCode, wParam, lParam);
}
The my main is
int main(int argc, char **argv)
{
_getch();
g_hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
cout << "Testing task keys disabling (alt tab, ctrl esc, alt esc) and taskbar..." << endl;
_getch();
UnhookWindowsHookEx( g_hKeyboardHook );
cout << "Re enabled" << endl;
_getch();
return 0;
}
I realize this code is for really old windows OS, but I've looked around and the other solutions resemble this code so I thought it should work.
But for some reason it doesn't seem to be working. Whenever my program gets to that line of code, the program stalls for like 5 seconds and continues to run, but the task keys are still working.
I've heard that I should be implementing that function as a dll instead of putting everything in one file, but I'm not sure if they're absolutely right (also I know nothing of dlls)
In addition, I've also tried code (to disable windows key) here: http://msdn.microsoft.com/en-us/library/windows/desktop/ee416808(v=vs.85).aspx and it does the same thing my own program (stalls and does nothing)
Can anyone spot where I did something wrong? I'm using VC++ 2010 on windows 7 64bit.
Your code is fine, hooks just doesn't work with console application because windows can't callback into a console application, it requires a message loop.
Read this answer by Hans Passant which applies here too.

Concatenation of pressed WM_Char key values win32API

I am trying to capture the values of WM_CHAR keys, and then putting all the captured the values into a single string. I have tried to concatenate the pressed key value 2, 3, 4 and 5 with _tcscat, the resulting TCHAR string looks like this "22232323423423452345" I would like to know how to make TCHAR string looks like 2345. The following is the code that I have.
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PMSG pmsg ;
int i, iType ;
int StrLen;
TCHAR StrBuf[9];
static TCHAR tBuf[32];
TCHAR MyTchar[8] = TEXT ("A");
WORD wCharCode;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect(hwnd, &rect);
SelectObject (hdc, GetStockObject (SYSTEM_FONT)) ;
SetBkMode (hdc, TRANSPARENT) ;
for (i = min (cLines, cLinesMax), cScreenLine=1; i>0 ; i--, cScreenLine++)
{
iType = pmsg[i-1].message == WM_CHAR ;
if (!iType)
{
StrLen= wsprintf(StrBuf, TEXT("%s"), TEXT(" "));
}
else
{
wCharCode = (WORD)(pmsg[i-1].wParam & 0xffff);
memcpy(&MyTchar, &wCharCode, 2);
StrLen = wsprintf(StrBuf[2], TEXT("%s"), &MyTchar);
_tcscat(tBuf, MyTchar);
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
}
I don't understand the message processing you have during the WM_PAINT message. You probably want to handle WM_CHAR as a separate message altogether where you can keep track of a string.
Outside of your WndProc, you will need #include <string>; and std::wstring keyPresses;
WM_CHAR can then be handled like any other event inside the WndProc.
case WM_CHAR:
switch (wParam)
{
// First, handle non-displayable characters by beeping.
case 0x08: // backspace.
case 0x09: // tab.
case 0x0A: // linefeed.
case 0x0D: // carriage return.
case 0x1B: // escape.
case 0x20: // space.
MessageBeep((UINT) -1);
break;
// Next, handle displayable characters by appending them to our string.
default:
keyPresses += (wchar_t) wParam;
}
break;
Then, you can do whatever manipulations you would like on this string, including displaying it during the WM_PAINT message.
Since you are using C++, use std::string or std::wstring. It will be much simpler and safer (no buffer overflows)
Before you use string buffer, you should clear them first.
You can use
1. ZeroMemery
2. memset
And or
TCHAR StrBuf[9];
====>
TCHAR StrBuf[9] = {0};
finally, why u use tBuf as a static var?