How to block printing functionality(CTRL + P) on windows text editors? - c

I want to block printing functionality(CTRL + P) on windows platform for specific applications. I am doing it using keyboard hook. I am able to detect CTRL + P but I am not able to stop it. I am returning from hook procedure in case of CTRL + P but application still receives this message and process printing.
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(
int nCode,
WPARAM wParam,
LPARAM lParam)
{
FILE* f1;
static WPARAM wPrevParam;
if (((DWORD)lParam & 0x40000000) && (HC_ACTION == nCode))
{
if ((wParam == VK_SPACE) || (wParam == VK_RETURN) || (wParam == VK_CONTROL) || (wParam >= 0x2f) && (wParam <= 0x100))
{
char ch;
f1 = fopen("d:\\report.txt", "a+");
if (wParam == VK_CONTROL)
{
if (wPrevParam == 0x50)// 0x50 = P
{
const char* text = "CTRL-P detected.";
fwrite(text, strlen(text), 1, f1);
fclose(f1);
wParam = 0;
lParam = 0;
return 1;
}
const char *text = "CTRL";
fwrite(text, strlen(text), 1, f1);
fprintf(f1, "%02X\n", (unsigned char)wParam);
}
else
{
wPrevParam = wParam;
}
fclose(f1);
}
}
LRESULT RetVal = CallNextHookEx(hkb, nCode, wParam, lParam);
return RetVal;
}

I want to block printing functionality(CTRL + P) on windows platform
for specific applications. I am doing it using keyboard hook. I am
able to detect CTRL + P but I am not able to stop it.
This blocks [Ctrl] + "P" in a WH_KEYBOARD_LL hook... but won't prevent printing by [File] [Print] or other way of course... =>
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
DWORD dwKey = 0;
if (HC_ACTION == nCode)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;
BOOL bCtlDown = GetKeyState(VK_CONTROL) < 0;
if (bCtlDown && dwKey == 'P')
{
Beep(6000, 10);
return 1;
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

Windows application to block CTRL + P using WH_KEYBORAD_LL hook works. So working code snippet will be as follows:
#include<fstream>
#include<windows.h>
using namespace std;
ofstream out("logs.txt", ios::out);
LRESULT CALLBACK keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static bool controlPressed = false;
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)(lParam);
if (wParam == WM_KEYDOWN)
{
if (p->vkCode == VK_LCONTROL || p->vkCode == VK_RCONTROL)
{
controlPressed = true;
}
else if (char(tolower(p->vkCode)) == 'p' && true == controlPressed)
{
out << "<CONTROL + P Detected>";
return 1;
}
else
{
controlPressed = false;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
HHOOK keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
keyboardHookProc,
hInstance,
0
);
MessageBox(NULL, TEXT("Press OK to stop blocking of printing."), TEXT("Information"), MB_OK);
out.close();
return 0;
}

Related

Message queue for two cpp file with windows API

To send the message in the Queue from one source file and get the message in another source file.I read the docs from Microsoft and try to implement as below
test2.c - post the message
main.c - get the Message
Testing1: If i execute the same code in single file that get executed and i receive the data
Testing : Same code is written in two separate file "if (msg.message == WM_YOUR_MESSAGE)" these statement does not get satisfied.
test2.h
typedef struct
{
int SomeData1;
int SomeData2;
int SomeDataN;
} MessageData;
/* Unique IDs for Window messages to exchange between the worker and the
GUI thread. */
#define WM_YOUR_MESSAGE ( WM_USER + 3 )
void __cdecl ThreadProc(void* aArg);
test2.c
#include <windows.h>
#include <process.h>
#include "malloc.h"
#include <stdio.h>
#include <test2.h>
volatile DWORD ThreadID_GUI;
void __cdecl ThreadProc(void* aArg)
{
MessageData* data;
for (;; )
{
Sleep(500);
/* Allocate memory for a new message data structure */
data = (MessageData*)malloc(sizeof(*data));
/* Initialize the message data structure with some information to transfer
to the GUI thread. */
data->SomeData1 = 1234;
data->SomeData2 = 4567;
data->SomeDataN = 7894;
PostThreadMessage(ThreadID_GUI, WM_YOUR_MESSAGE, 0, (LPARAM)data);
}
}
main.c
#include <windows.h>
#include <tchar.h>
#include <process.h>
#include "malloc.h"
#include "stdio.h"
#include<test2.h>
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
ThreadID_GUI = GetCurrentThreadId();
/* Start some background thread */
_beginthread(ThreadProc, 0, 0);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTMESSAGEQUEUE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTMESSAGEQUEUE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
/* STEP 3: React on the message sent from the foreign thread */
if (msg.message == WM_YOUR_MESSAGE)
{
MessageData* tmp = (MessageData*)msg.lParam;
if (tmp->SomeData1 == 1234) {
printf("someData\n");
}
/* Free the data structure associated to the message */
free(tmp);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_CLIENTMQ));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_CLIENTMQ);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance,
nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd,
About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM
lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
After filling all the missing information in your source, and removing useless code, I have your code working.
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>
#include "test2.h"
HINSTANCE hInst;
LPCWSTR szWindowClass = L"Piu";
LPCWSTR szTitle = L"Title";
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
/*
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd,
About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
*/
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
/*
wcex.hIcon = LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_CLIENTMQ));
wcex.hIconSm = LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_SMALL));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_CLIENTMQ);
*/
wcex.lpszClassName = szWindowClass;
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance,
NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
ThreadID_GUI = GetCurrentThreadId();
/* Start some background thread */
_beginthread(ThreadProc, 0, 0);
// Initialize global strings
// LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
// LoadStringW(hInstance, IDC_TESTMESSAGEQUEUE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
// HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTMESSAGEQUEUE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
/* STEP 3: React on the message sent from the foreign thread */
if (msg.message == WM_YOUR_MESSAGE)
{
MessageData* tmp = (MessageData*)msg.lParam;
if (tmp->SomeData1 == 1234) {
printf("someData\n");
}
/* Free the data structure associated to the message */
free(tmp);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
test2.c:
#include <Windows.h>
#include "test2.h"
volatile DWORD ThreadID_GUI;
void __cdecl ThreadProc(void* aArg)
{
MessageData* data;
for (;; )
{
Sleep(500);
/* Allocate memory for a new message data structure */
data = (MessageData*)malloc(sizeof(*data));
/* Initialize the message data structure with some information to transfer
to the GUI thread. */
data->SomeData1 = 1234;
data->SomeData2 = 4567;
data->SomeDataN = 7894;
PostThreadMessage(ThreadID_GUI, WM_YOUR_MESSAGE, 0, (LPARAM)data);
}
}
test2.h
typedef struct
{
int SomeData1;
int SomeData2;
int SomeDataN;
} MessageData;
/* Unique IDs for Window messages to exchange between the worker and the
GUI thread. */
#define WM_YOUR_MESSAGE ( WM_USER + 3 )
void __cdecl ThreadProc(void* aArg);
extern volatile DWORD ThreadID_GUI;
I removed menu and icons so there is no .rc file.

Column filter in ListView on win api

I'm doing some research and I would like to know how I can implement a column filter in a ListView using purely win32 api.
Something like this:
I wrote a simple test code, to generate a List View to show the CSV content.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <commctrl.h>
#include <string.h>
#define WND_CLASS_NAME "CSVVIEW"
char* filename;
HWND hList;
int rgb(int r, int g, int b) { return r + (g << 8) + (b << 16); }
void onCreate(HWND hWnd, LPARAM lParam) {
LVCOLUMN col;
LVITEM item;
int iCol, iCount, dwStyle;
CREATESTRUCT* lp = (CREATESTRUCT*)lParam;
FILE* fp;
char buf[256];
char* field;
memset(&item, 0, sizeof(item));
hList = CreateWindowEx(0, WC_LISTVIEW, 0,
WS_CHILD | WS_VISIBLE | LVS_REPORT,
0, 0, 100, 100, hWnd, (HMENU)1, lp->hInstance, NULL);
dwStyle = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
dwStyle = dwStyle | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT |
LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP;
SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
fp = fopen(filename, "r");
if (fp == NULL) {
sprintf(buf, "Fail to open the file...", filename);
MessageBox(hWnd, buf, "Error", MB_OK);
exit(1);
}
fgets(buf, 255, fp);
field = strtok(buf, ",");
for (iCol = 0; field != NULL; iCol++) {
if (field[1] != ':') { col.fmt = LVCFMT_LEFT; }
else if (field[0] == 'l') { col.fmt = LVCFMT_LEFT; field += 2; }
else if (field[0] == 'c') { col.fmt = LVCFMT_CENTER; field += 2; }
else if (field[0] == 'r') { col.fmt = LVCFMT_RIGHT; field += 2; }
col.cx = strlen(field) * 13;
col.iSubItem = iCol;
col.pszText = field;
SendMessage(hList, LVM_INSERTCOLUMN, iCol, (LPARAM)&col);
field = strtok(NULL, ",\n");
}
item.mask = LVIF_TEXT;
for (iCount = 0; fgets(buf, 255, fp) != NULL; iCount++) {
item.pszText = strtok(buf, ",");
item.iItem = iCount;
item.iSubItem = 0;
SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&item);
for (iCol = 1; (field = strtok(NULL, ",\n")) != NULL; iCol++) {
item.pszText = field;
item.iItem = iCount;
item.iSubItem = iCol;
SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&item);
}
}
}
void onSize(HWND hwnd, WPARAM wp, LPARAM lp) {
RECT rc;
GetClientRect(hwnd, &rc);
MoveWindow(hList, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}
int onNotify(HWND hwnd, WPARAM wp, LPARAM lp) {
NMHDR* pnmhdr = (NMHDR*)lp;
if (pnmhdr->code == NM_CUSTOMDRAW) {
NMLVCUSTOMDRAW* lpCustomDraw = (NMLVCUSTOMDRAW*)pnmhdr;
switch (lpCustomDraw->nmcd.dwDrawStage) {
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
if (lpCustomDraw->nmcd.dwItemSpec % 2 == 1)
lpCustomDraw->clrTextBk = rgb(209, 240, 179);
else
lpCustomDraw->clrTextBk = rgb(250, 250, 250);
return CDRF_NEWFONT;
}
}
return DefWindowProc(hwnd, WM_NOTIFY, wp, lp);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE: onCreate(hWnd, lParam); break;
case WM_SIZE: onSize(hWnd, wParam, lParam); break;
case WM_NOTIFY: return onNotify(hWnd, wParam, lParam);
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
char buf[256];
HWND hWnd;
WNDCLASS wcl;
MSG msg;
filename = lpCmdLine;
if (filename == NULL) return FALSE;
InitCommonControls();
memset(&wcl, 0, sizeof(wcl));
wcl.hInstance = hInstance;
wcl.lpszClassName = WND_CLASS_NAME;
wcl.lpfnWndProc = WindowProc;
wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
wcl.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
if (!RegisterClass(&wcl)) return FALSE;
wsprintf(buf, "%s - %s", "CSV View", lpCmdLine);
hWnd = CreateWindowEx(0, WND_CLASS_NAME, buf,
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 900, 300, NULL, NULL, hInstance, NULL);
if (!hWnd) return FALSE;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
CSV test file:
COL 1,COL 2,COL 3,COL 4
CA_002,CB_002,CB_002,CB_002
CA_003,CB_003,CB_003,CB_003
What is necessary to change in the code so that it is possible to create the search fields in the list view header?
How to capture the events for each text field in the Header?

SetWindowsHookEx - difference between VK_LSHIFT and "Search" keyboard button

I use SetWindowsHookEx to catch keyboard events
SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)
Here is HookCallback
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
if (wParam == WM_KEYDOWN)
{
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
printf("%ld\n", kbdStruct.vkCode);
}
}
}
When press "left shift" output is
160
when press "search" button (button with loupe icon on notebooks) output is
160
91
132
How to check if "left shift" or "search" button is pressed inside HookCallback ?
160 is VK_LSHIFT, 91 is VK_LWIN, and 132 is VK_F21. See Virtual-Key Codes. The only standardized Search key is VK_BROWSER_SEARCH, so clearly your keyboard manufacturer is using a non-standard key for its Search key.
You need to remember the keys you see from one event to the next as needed, eg:
bool LeftShiftIsDown = false;
bool LeftWinIsDown = false;
bool F21IsDown = false;
bool SearchIsDown = false;
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
KBDLLHOOKSTRUCT *kbdStruct = (KBDLLHOOKSTRUCT*) lParam;
if (wParam == WM_KEYDOWN)
{
printf("%ld is down\n", kbdStruct->vkCode);
switch (kbdStruct->vkCode)
{
case VK_LSHIFT:
LeftShiftIsDown = true;
break;
case VK_LWIN:
LeftWinIsDown = true;
break;
case VK_F21:
F21IsDown = true;
break;
}
if (LeftShiftIsDown && LeftWinIsDown && F21IsDown)
{
if (!SearchIsDown)
{
SearchIsDown = true;
printf("Search is down\n");
}
}
}
else if (wParam == WM_KEYUP)
{
printf("%ld is up\n", kbdStruct->vkCode);
switch (kbdStruct->vkCode)
{
case VK_LSHIFT:
LeftShiftIsDown = false;
break;
case VK_LWIN:
LeftWinIsDown = false;
break;
case VK_F21:
F21IsDown = false;
break;
}
if (!(LeftShiftIsDown && LeftWinIsDown && F21IsDown))
{
if (SearchIsDown)
{
SearchIsDown = false;
printf("Search is up\n");
}
}
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}

How can I center a Dialog Box over main program window position?

I've got this code to open an InputBox defined on a DLL that get HMODULE that I save on hInstance variable when main program calls. How can I center it over the main program window?
It occurs that doesn't work and shows the DialogBox on top left on Screen or on top left of program window randomly.
#include <windows.h>
#include "resource.h"
char IB_res[10];
double defaultValue = 0;
BOOL CALLBACK InputBox_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
if (defaultValue != -1)
SetDlgItemText(hwnd, IDC_EDIT, (LPCSTR)(my_printf("%f", defaultValue).c_str()));
else
SetDlgItemText(hwnd, IDC_EDIT, (LPCSTR)"");
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
if (!GetDlgItemText(hwnd, IDC_EDIT, IB_res, 10))
*IB_res = 0;
case IDCANCEL:
EndDialog(hwnd, wParam);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
DWORD processId;
HWND hwndParent;
BOOL CALLBACK enumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD procid;
GetWindowThreadProcessId(hwnd, &procid);
if (procid == processId)
hwndParent = hwnd;
return TRUE;
}
HINSTANCE hInstance;
const char* InputBox(double def_value)
{
defaultBetValue = def_value;
processId = GetCurrentProcessId();
EnumWindows(enumWindowsProc, 0);
INT_PTR ret = DialogBox(hInstance, MAKEINTRESOURCE(IDD_IB), hwndParent, InputBox_WndProc);
DWORD error = GetLastError();
if (ret != IDOK)
*IB_res = 0;
return IB_res;
}
From:
http://msdn.microsoft.com/en-gb/library/windows/desktop/ms644996(v=vs.85).aspx
case WM_INITDIALOG:
// Get the owner window and dialog box rectangles.
if ((hwndOwner = GetParent(hwndDlg)) == NULL)
{
hwndOwner = GetDesktopWindow();
}
GetWindowRect(hwndOwner, &rcOwner);
GetWindowRect(hwndDlg, &rcDlg);
CopyRect(&rc, &rcOwner);
// Offset the owner and dialog box rectangles so that right and bottom
// values represent the width and height, and then offset the owner again
// to discard space taken up by the dialog box.
OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect(&rc, -rc.left, -rc.top);
OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining space and the owner's
// original position.
SetWindowPos(hwndDlg,
HWND_TOP,
rcOwner.left + (rc.right / 2),
rcOwner.top + (rc.bottom / 2),
0, 0, // Ignores size arguments.
SWP_NOSIZE);
if (GetDlgCtrlID((HWND) wParam) != ID_ITEMNAME)
{
SetFocus(GetDlgItem(hwndDlg, ID_ITEMNAME));
return FALSE;
}
return TRUE;

Screen is flickering even when using doublebuffering

I am totally new in programming.
For my first programm I tried to make a small game in c with windows api.
the following code is a nearly working snake, (some bugs not fixed yet)
but i cant find a working solution to fix that flickering.
(I dont know double Buffering so I just took from here: [http://www.codeguru.com/forum/archive/index.php/t-272723.html][1]
// snake1.02.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "snake1.02.h"
#include "stdio.h"
#define ID_MYTIMER 1234567
#define ID_BERRY 1
#define SEGMENTSIZE 10
const WCHAR szClassName[] = L"Snake1.02";
HWND hWnd;
UINT myTimer;
struct point {
int x, y;
};
point snake[500];
int dx = SEGMENTSIZE; //Change direction l=l+1
int dy = 0;
int snakelength=3;
int highscore=0;
WCHAR nachricht[100];
int map[80][60]; //Wenn Bildschirmgröße angepasst wird, auch hier anpassen!!!
// Global Variables:
HINSTANCE hInst; // current instance
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
// Initialize global strings
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
myTimer = SetTimer ( hWnd, ID_MYTIMER, 40, NULL );
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
KillTimer ( hWnd, myTimer );
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+2);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szClassName;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szClassName, szClassName, WS_OVERLAPPED,
CW_USEDEFAULT, 0, 800, 600, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
for(int i=snakelength; i>=0; i--){
snake[i].x =100-(i*SEGMENTSIZE);
snake[i].y=20;}
for(int x=0; x<78;x++){
map[x][0]=1;
map[x][56]=1;
}
for(int y=0; y<57;y++){
map[0][y]=1;
map[78][y]=1;
}
map[50][70]=2;
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HDC memDC;
HBITMAP hMemBmp;
HBITMAP hOldBmp;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
memDC = CreateCompatibleDC(hdc); //flimmerfrei
hMemBmp = CreateCompatibleBitmap(hdc, 800, 600);
hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);
// TODO: Add any drawing code here...
for (int i = 0; i<=snakelength; i++) {
Rectangle(memDC, snake[i].x,snake[i].y,snake[i].x+10,snake[i].y+10);
}
for (int y=0; y<60;y++){
for (int x=0; x<80;x++){
if(map[x][y]==1||map[x][y]==2){
Rectangle(memDC,x*SEGMENTSIZE,y*SEGMENTSIZE,x*SEGMENTSIZE+SEGMENTSIZE,y*SEGMENTSIZE+SEGMENTSIZE);
}}
}
BitBlt(hdc, 0, 0, 800, 600, memDC, 0, 0, SRCCOPY);
SelectObject(memDC, hOldBmp);
DeleteObject(hMemBmp);
DeleteDC(memDC);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_TIMER:
switch (wParam)
{
case ID_MYTIMER: {
if (map[snake[0].x/10][snake[0].y/10]==1){ //crashcheck
KillTimer ( hWnd, myTimer );
wsprintf (nachricht,L"Game Over. Punktestand: %d",highscore);
MessageBox(hWnd, (LPCWSTR)nachricht,L"Ende",0);
}
if (map[snake[0].x/10][snake[0].y/10]==2) //grow
{
for (int i = snakelength; i>0; i--)
{
snake[i].x = snake[i-1].x;
snake[i].y = snake[i-1].y;
}
snake[0].x = snake[1].x + dx;
snake[0].y = snake[1].y + dy;
map[snake[0].x/10][snake[0].y/10]=0;
snakelength++;
highscore+=10;
}
for (int i = snakelength; i>0; i--) {
snake[i].x = snake[i-1].x;
snake[i].y = snake[i-1].y;
}
snake[0].x = snake[1].x + dx;
snake[0].y = snake[1].y + dy;
InvalidateRect(hWnd, 0,1);
return 0;
}
}
break;
case WM_KEYDOWN: {
switch (wParam) {
case VK_DOWN:{
if(dy!=-SEGMENTSIZE){
dy=SEGMENTSIZE;
dx=0;
}
}
break;
case VK_RIGHT:{
if (dx!=-SEGMENTSIZE){
dy=0;
dx=SEGMENTSIZE;
}
}
break;
case VK_UP:{
if (dy!=SEGMENTSIZE){
dy=-SEGMENTSIZE;
dx=0;
}
}
break;
case VK_LEFT:{
if(dx!=SEGMENTSIZE){
dy=0;
dx=-SEGMENTSIZE;
}
}
break;
case VK_ESCAPE:{
ExitProcess(0);
}
break;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Add one case to your main switch statement in WndProc:
case WM_ERASEBKGND:
return TRUE;

Resources