Reading bits from the bin value - c++

What is the order one has to read the bits from the bin value? Having for e.g. this official MS doc site regarding the lParam of the WM_CHAR message, they explain what bits have what meaning. Taking the bits 16-23 for the scan code value should I read the bits from right to left or vice versa?

The page you linked to uses LSB 0 bit numbering so you can extract bits 16-23 with
lParam & 0b00000000111111110000000000000000U
// | | | |
// bit 31 23 16 0
// MSB LSB
Note: The 0b prefix for binary numbers requires C++14. In C it's only available as an extension in some implementations.
You may also want to shift down the result with
(lParam & 0b00000000111111110000000000000000U) >> 16U
or simpler
(lParam >> 16U) & 0b11111111U // or (lParam >> 16U) & 0xFFU

two ways:
UINT bitsxtractBits(UINT val, int startBit, int nbits)
{
UINT mask = ((UINT)1 << nbits) - 1;
return (val & mask) >> startBit;
}
//note it will not work if you want to extract all bits (in this case 32).
//but in this case you do not need to extract them :)
and the usage to extract your bits:
bitsxtractBits(message, 16, 8)
or
union WM_CHAR_message
{
struct
{
UINT repatCount : 16;
UINT scanCode : 8;
UINT : 4;
UINT contextCode : 1;
UINT previousState : 1;
UINT transitionState : 1;
};
UINT raw;
};
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
union WM_CHAR_message msgu;
//C++ safe
memcpy(&msgu, &message, sizeof(msgu)); // will be optimized to the store instruction only
switch (message)
{
// ...
case WM_CHAR:
switch(msgu.scanCode)
{
//....
}
OnKeyPress(wParam);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

Related

follow official direct2d sample but got access violation error [duplicate]

This question already has answers here:
Direct2D : Unhandled Exception In WM_RESIZE switch case
(2 answers)
Closed 3 years ago.
Following the official tutorial of Direct2D (https://learn.microsoft.com/en-us/windows/win32/direct2d/direct2d-quickstart) to create a sample project with Visual Studio 2019. When running the code in x86, everything works fine while changing the platform to x64, I get an error that says: 'Exception thrown: read access violation.' in SampleD2D.cpp. (the line was commented in the code below)
the error is :
Exception thrown: read access violation.
this was 0xBB18F6E8.
LRESULT CALLBACK DemoApp::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
if (message == WM_CREATE)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
DemoApp* pDemoApp = (DemoApp*)pcs->lpCreateParams;
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
PtrToUlong(pDemoApp)
);
result = 1;
}
else
{
DemoApp* pDemoApp = reinterpret_cast<DemoApp*>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));
bool wasHandled = false;
if (pDemoApp)
{
switch (message)
{
case WM_SIZE:
{
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
pDemoApp->OnResize(width, height); // throw the error!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
result = 0;
wasHandled = true;
break;
case WM_DISPLAYCHANGE:
{
InvalidateRect(hwnd, NULL, FALSE);
}
result = 0;
wasHandled = true;
break;
case WM_PAINT:
{
pDemoApp->OnRender();
ValidateRect(hwnd, NULL);
}
result = 0;
wasHandled = true;
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
result = 1;
wasHandled = true;
break;
}
}
if (!wasHandled)
{
result = DefWindowProc(hwnd, message, wParam, lParam);
}
}
return result;
}
Unfortunately, I'm no WinAPI expert but, out of curiosity, I googled a bit. Now, I'm quite sure about OPs problem:
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
PtrToUlong(pDemoApp)
);
specifically PtrToUlong(pDemoApp).
That might work for 32 bit applications but not for 64 bit.
long is in MS VC++ 32 bit – for x86 as well as x64 platform.
Hence, converting a pointer to long or unsigned long is good for making it wrong on x64 (as soon as the upper 32 bits are not 0 – which is probably hard to predict).
Googling into this direction I found e.g. PtrToUlong Q/A on gamedev.net with this (old) answer:
msdn, try to avoid using these because you are casting a pointer into an unsigned long. This may work correctly on 32-bit executables but if you compile in 64-bit you may have problems.
which supports my doubts.
According to MS doc. SetWindowLongPtrW function, the signature is:
LONG_PTR SetWindowLongPtrW(
HWND hWnd,
int nIndex,
LONG_PTR dwNewLong
);
So, this should fix it:
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(pDemoApp)
);
Please, note the MS doc. about LONG_PTR:
LONG_PTR
A signed long type for pointer precision. Use when casting a pointer to a long to perform pointer arithmetic.
This type is declared in BaseTsd.h as follows:
C++
#if defined(_WIN64)
typedef __int64 LONG_PTR;
#else
typedef long LONG_PTR;
#endif
Btw. I didn't understand as well
DemoApp* pDemoApp = reinterpret_cast<DemoApp*>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(
hwnd,
GWLP_USERDATA
)));
According to doc. GetWindowLongPtrW function, the function returns LONG_PTR. So, why the static_cast<LONG_PTR>? A type cast should be always the last resort if absolutely necessary. (Although, I admit that WinAPI is probably unusable without.)

Keyboard hook not restricting key press correctly

I have a dll that is injected into a specific process with the intention of restricting certain key presses from being sent to the aforementioned process..
This seems to work, with one major flaw.. When the keys are pressed that I intend to restrict, they are still being passed to the process.
I added the line to raise a message box whenever the hook should be returning the value of 1 (restricting the keys from progressing further own the chain), and the message box is raised, and even stranger, the key is stopped from progressing, but whenever I remove the messagebox code the restriction is completely ignored!!
Could anyone highlight what I am doing wrong? Or in the unlikely scenario that it is not my own wrongdoing, but some quirk that I am not aware of, please do let me know.
Many thanks.
Here is my hook proc code, which I expect is where the issue lies.
extern "C" __declspec(dllexport) int KeyboardHook(INT nCode, WPARAM wParam, LPARAM lParam) {
//-- Return unless valid nCode
if (nCode < 0) return CallNextHookEx(keyhook_handle, nCode, wParam, lParam);
//-- Setup some bools
BOOL alt_down = ((lParam & (1U << 29)) == 1);
BOOL key_last = ((lParam & (1U << 30)) == 0);
BOOL key_down = ((lParam & (1U << 31)) == 0);
BOOL let_pass = TRUE;
//-- Checks for keypresses
if (key_last && key_down) {
if (wParam == VK_F12) let_pass = FALSE;
if ((wParam == VK_RETURN) && alt_down) let_pass = FALSE;
}
//-- If not let_pass then return 1 to restrict key
if (!let_pass) {
//MessageBox(NULL, L"Key Stopped", L"Info:", MB_OK | MB_ICONERROR);
return 1;
}
//-- Call the next hook in the chain
return CallNextHookEx(keyhook_handle, nCode, wParam, lParam);
}

Input validation of a subclassed edit control to only accept floating point numbers

On my current project I have been struggling the last couple of days with subclassing edit boxes. By now I successfully subclassed my edit box and validated the input such that it only accepts digits, commas, a minus sign and keyboard commands.
But for quite a while I'm now stuck with the refinement of the input validation. I want my edit box to behave as the following:
accept minus sign only at first position
accept only one leading zero
accept only one comma
force comma after leading zero
manage those cases when deleting single characters or selections of the text via 'back', 'delete', select-all and then pasting something over it
My code in its current form looks like this and provides almost none of the advanced validation requirements I specified above:
inline LRESULT CALLBACK decEditBoxProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
UINT_PTR uIdSubclass,
DWORD_PTR dwRefData)
{
if(msg == WM_CHAR)
{
decEditBoxData* data = reinterpret_cast<decEditBoxData*>(ULongToPtr(dwRefData));
bool isDigit = (wParam >= '0' && wParam <= '9');
bool isZero = ((wParam == '0') && !data->blockZero);
bool isSign = (wParam == '-');
bool isComma = ((wParam == '.' || wParam == ',') && !data->blockComma);
bool isValidCommand = (wParam == VK_RETURN
|| wParam == VK_DELETE
|| wParam == VK_BACK);
// Restrict comma to one.
if(isComma && data->nCommas > 0)
return FALSE;
else if(isComma && data->nCommas == 0)
data->nCommas++;
// Restrict trailing zeroes to one.
if(isZero && data->nTrailingZeroes > 0)
return FALSE;
else if(isZero && data->nTrailingZeroes == 0)
data->nTrailingZeroes++;
// Filter everything but digits, commas and valid commands.
if(!isDigit && !isValidCommand && !isComma)
return FALSE;
}
return DefSubclassProc(hWnd, msg, wParam, lParam);
}
Any idea on how to algorithmically solve this problem is very appreciated.
UPDATE
Thanks to the suggestions of David Heffernan and IInspectable I was able to (almost) solve my problem without subclassing the edit controls.
In the dialog procedure (thats contains the edit controls):
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_IN_REAL:
if(HIWORD(wParam)==EN_CHANGE) onEditChange(hDlg, IDC_IN_REAL);
break;
case IDC_IN_IMAG:
if(HIWORD(wParam)==EN_CHANGE) onEditChange(hDlg, IDC_IN_IMAG);
break;
}
break;
}
With onEditChange:
void onEditChange(HWND hDlg, int ctrlID)
{
HWND hEdit = GetDlgItem(hDlg, ctrlID);
size_t len = GetWindowTextLength(hEdit)+1;
wchar_t* cstr = new wchar_t[len];
GetWindowText(hEdit, cstr, len);
std::wstring wstr(cstr);
if(!(tools::isFloat(wstr)))
{
EDITBALLOONTIP bln;
bln.cbStruct = sizeof(EDITBALLOONTIP);
bln.pszTitle = L"Error";
bln.pszText = L"Not a valid floating point character.\nUse '.' instead of ','";
bln.ttiIcon = TTI_ERROR;
Edit_ShowBalloonTip(hEdit, &bln);
}
delete [] cstr;
}
and isFloat():
bool tools::isFloat(std::wstring str)
{
std::wistringstream iss(str);
float f;
wchar_t wc;
if(!(iss >> f) || iss.get(wc))
return false;
return true;
}
I will probably add some more visual feedback for the user, but that's not important right now.
The question however, is not answered yet. My intention was to allow the "," as a possible decimal point.
You need a state machine. First declare your states.
enum InputState
{
NoCharacters
MinusSign
LeadingZero
PreDecimalPoint
PostDecimalPoint
}
InputState mState = NoCharacters
Whenever the user inputs a character, call a different validation function depending on the value of mState using a switch block.
bool ValidCharacter(char input)
{
switch (mState)
{
case NoCharacters:
return NoCharacters(input);
case MinusSign:
return MinusSign(input);
/// etc
}
}
So for example, the function you call when mState == NoCharacters, would accept any number, decimal point or minus sign.
It would then change mState to MinusSign if the character was a minus sign, LeadingZero if it was a zero, etc.

reading from ComboBox

how can i read the text of a selected value of a comboBox in windows aplication(borland C++) for example:
i have combobox which contains 2 values (sum and mult) i want to see if it is sum i have to add the numbers and if it mult i have to multiplicate the numbers so how can i read the value of combobox in this case.
For Windows:
In your window procedure use the WM_COMMAND message and then check for a CBN_SELCHANGE notification. Then use WM_GETTEXT along with WM_GETTEXTLENGTH to receive the selected text like Mark Ingram says. Or you can also use CB_GETCURSEL to receive the identifier of the selected item.
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDC_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE) {
HWND hCtl = GetDlgItem(hWnd, IDC_COMBO);//Get handle for HMENU item
if (SendMessage(hCtl, CB_GETCURSEL, 0, 0) == compareValue) {
//...
}
}
break;
}
break;
//...
}
}
Assuming that you are using Windows, you can use the following messages:
WM_GETTEXTLENGTH and WM_GETTEXT.
Firstly, get the length of the selected text, then allocate your buffer to ensure it's large enough, then retrieve the actual text. Easy.
Example:
const UINT length = ::SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0);
LPTSTR pszText = new TCHAR[length + 1];
::SendMessage(hWnd, WM_GETTEXT, length + 1, pszText);
// pszText will now contain the text you want, do what you want with it
delete[] pszText; // Remember to delete else you will leak.
I never work with c++ with winapplication but i tried it with the c# and hopefully that you want the desired output as i got through your question if it is not right then you should edit your question.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Text == "ADD")
{
int a = 12, b = 13, c;
c = a + b;
MessageBox.Show("Result of adding= " + c);
}
else if (comboBox1.Text == "Multiple")
{
int x = 3, y = 5, z;
z = x * y;
MessageBox.Show("Result of multiplication= " + z);
}
}

Convert a virtual-key code to a unicode character - WinApi C++

I am trying to convert a virtual-key code to a unicode character. The virtual-key codes are received from a low level keyboard hook.
LRESULT __stdcall hook_callback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0 && wParam == WM_KEYDOWN)
{
const auto kbd_hook = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
BYTE state[256];
GetKeyboardState(state);
WCHAR key_buffer[2];
ToUnicode(kbd_hook->vkCode, kbd_hook->scanCode, state, key_buffer, 2, 0);
// handle key_buffer...
}
return CallNextHookEx(hook, nCode, wParam, lParam);
}
This works fine except for the fact that Shift and Caps Lock are not taken into account. Pressing Shift + 1 will result in 1, instead of the expected ! (assuming the locale is US). However, if I fill the state buffer by individually getting each key, it works as expected:
BYTE state[256];
for (SHORT i = 0; i < 256; ++i) {
const SHORT key_state = GetKeyState(i);
// Right shifts the high order bit by 8 to avoid a narrowing
// conversion from SHORT to BYTE.
state[i] = (key_state >> 8) | (key_state & 1);
}
If I fill the state buffer like so, pressing Shift + 1 will result in ! as expected.
Why does GetKeyState() work but GetKeyboardState() doesn't?