da_mango_bros
asked on
INSTALIZE ARRAY/STRUCTURE AT DECLARATION - EXTREMELY DIFFICULT
hi.
working with these structures:
typedef struct tagINPUT {
DWORD type;
union {
MOUSEINPUT mi;
KEYBDINPUT ki;
HARDWAREINPUT hi;
};
} INPUT, *PINPUT;
typedef struct tagKEYBDINPUT {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
i want to get the following result:
type = INPUT_KEYBOARD
ki.wVk = VK_CAPITAL
ki.wScan = 0
ki.dwFlags = KEYEVENTF_EXTENDEDKEY
ki.time = 0
ki.dwExtraInfo = 0
But first union member is MOUSEINPUT mi, so this becomes very hard.
because i am using shared memory in a dll, i must assign the values upon declaration.
if any1 has any solutions to this problem, then pls let me know
thanks in advance,
suma
working with these structures:
typedef struct tagINPUT {
DWORD type;
union {
MOUSEINPUT mi;
KEYBDINPUT ki;
HARDWAREINPUT hi;
};
} INPUT, *PINPUT;
typedef struct tagKEYBDINPUT {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
i want to get the following result:
type = INPUT_KEYBOARD
ki.wVk = VK_CAPITAL
ki.wScan = 0
ki.dwFlags = KEYEVENTF_EXTENDEDKEY
ki.time = 0
ki.dwExtraInfo = 0
But first union member is MOUSEINPUT mi, so this becomes very hard.
because i am using shared memory in a dll, i must assign the values upon declaration.
if any1 has any solutions to this problem, then pls let me know
thanks in advance,
suma
>>because i am using shared memory in a dll, i must assign the values upon declaration.
You only need to initialize the values with arbitrary data. But, you can simply use
INPUT in = { INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0};
You only need to initialize the values with arbitrary data. But, you can simply use
INPUT in = { INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0};
ASKER
i originally tried to use:
INPUT input = {INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0}};
but because "mi" is first, i thought that {VK_CAPTIAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0} gets assigned to "mi", rather than to "ki" as required.
is there a way around this?
sefan73:
u misunderstood the question. i need to create a new instance of these structures, assign values to the variables, and then pass the new instances of the structures into functions as parameters.
because i am using shared memory in a dll, i cannot use:
int x;
x = 1;
but must use:
int x = 1;
this becomes difficult because of the union in one of the structures
INPUT input = {INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0}};
but because "mi" is first, i thought that {VK_CAPTIAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0} gets assigned to "mi", rather than to "ki" as required.
is there a way around this?
sefan73:
u misunderstood the question. i need to create a new instance of these structures, assign values to the variables, and then pass the new instances of the structures into functions as parameters.
because i am using shared memory in a dll, i cannot use:
int x;
x = 1;
but must use:
int x = 1;
this becomes difficult because of the union in one of the structures
You can use either
INPUT in = { INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0};
or
INPUT in = { INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0}};
INPUT in = { INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0};
or
INPUT in = { INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0}};
ASKER
i gave that a try and it didnt completly work.
here is my code from the HookProc of a keyboard hook, designed to toggle the capslock key each time a key is pressed:
//instalized in the shared memory section:
INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
//in the HookProc:
SendInput(2, input, sizeof(INPUT));
it works the first time i press a key (regardless of the state of capslock), but after that it dosnt work for some reason
it must be something to do with the instalization, cuz when i tried creating new variables each time, it worked.
here is my code from the HookProc of a keyboard hook, designed to toggle the capslock key each time a key is pressed:
//instalized in the shared memory section:
INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
//in the HookProc:
SendInput(2, input, sizeof(INPUT));
it works the first time i press a key (regardless of the state of capslock), but after that it dosnt work for some reason
it must be something to do with the instalization, cuz when i tried creating new variables each time, it worked.
>>//in the HookProc:
>>SendInput(2, input, sizeof(INPUT));
So, why would you need a global shared variable for that, you can simply make the array a local variable of your hooc proc...
>>SendInput(2, input, sizeof(INPUT));
So, why would you need a global shared variable for that, you can simply make the array a local variable of your hooc proc...
da_mango_bros,
> but because "mi" is first, i thought that {VK_CAPTIAL, 0, KEYEVENTF_EXTENDEDKEY,
> 0, 0} gets assigned to "mi", rather than to "ki" as required.
>
> is there a way around this?
Yes, move the "KEYBDINPUT ki;" to the top of the union. Unions don't have an order, as every element starts at the same address, anyway.
Stefan
> but because "mi" is first, i thought that {VK_CAPTIAL, 0, KEYEVENTF_EXTENDEDKEY,
> 0, 0} gets assigned to "mi", rather than to "ki" as required.
>
> is there a way around this?
Yes, move the "KEYBDINPUT ki;" to the top of the union. Unions don't have an order, as every element starts at the same address, anyway.
Stefan
da_mango_bros,
The probably cleanest way is to define INPUT_UNDEFINED as a fourth possible value for type, indicating that there is no real data in the union.
Stefan
The probably cleanest way is to define INPUT_UNDEFINED as a fourth possible value for type, indicating that there is no real data in the union.
Stefan
>>Yes, move the "KEYBDINPUT ki;" to the top of the union
Might be a long way down the road. Do you thing mailing that request to Bill Gates directly could help speeding that up? :o)
Might be a long way down the road. Do you thing mailing that request to Bill Gates directly could help speeding that up? :o)
ASKER
jkr:
yea that works... but it is ineffecient to create new variables each time a key is pressed
this code works fine:
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
INPUT input[2];
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki = keyDown;
input[1].ki = keyUp;
SendInput(2, input, sizeof(INPUT));
but when i change the code, leaving it in the hook proc (i.e. local), to:
INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
it dosnt work. clearly the last implementation is cleaner, replacing about 15 lines of code with 5
stefan73:
>> unions dont have an order
omg i never realized that... but can u explain why the code dosnt work then??
yea that works... but it is ineffecient to create new variables each time a key is pressed
this code works fine:
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
INPUT input[2];
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki = keyDown;
input[1].ki = keyUp;
SendInput(2, input, sizeof(INPUT));
but when i change the code, leaving it in the hook proc (i.e. local), to:
INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
it dosnt work. clearly the last implementation is cleaner, replacing about 15 lines of code with 5
stefan73:
>> unions dont have an order
omg i never realized that... but can u explain why the code dosnt work then??
>>yea that works... but it is ineffecient to create new variables each time a key is pressed
No. Just create it as
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
Anyway, you can keep that as a global variable, but the bottom line is that it does not have to be in a shared memory section...
No. Just create it as
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
Anyway, you can keep that as a global variable, but the bottom line is that it does not have to be in a shared memory section...
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
That is wrong as the parameters 2 - 5 get assigned to struct MOUSEINPUT and not to KEYINPUT, thus values like KEYEVENTF_EXTENDEDKEY will not properly assigned to input[0].ki.dwFlags but to input[0].mi.mouseData which has the same storage as input[0].ki.time. Look at this code:
bool operator==(const KEYBDINPUT& k1, const KEYBDINPUT& k2)
{
return (k1.dwExtraInfo == k2.dwExtraInfo) &&
(k1.dwFlags == k2.dwFlags) &&
(k1.time == k2.time) &&
(k1.wScan == k2.wScan) &&
(k1.wVk == k2.wVk);
}
bool operator==(const INPUT& i1, const INPUT& i2)
{
return (i1.type == i2.type) && (i1.ki == i2.ki);
}
void g()
{
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
INPUT input[2];
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki = keyDown;
input[1].ki = keyUp;
INPUT inputx[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
bool b1 = (input[0] == inputx[0]); // b1 = false;
bool b2 = (input[1] == inputx[1]); // b2 = false;
}
You may 'fix' the problem using this:
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY, 0, 0, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0, 0, 0}
};
Now KEYBDINPUT is correct as the first two members of KEYBDINPUT have WORD type and third is a DWORD whereas MOUSEINPUT starts with two LONG members. The two WORD members get mapped to the first LONG, and the DWORD get mapped to second LONG.
However, i would use the assign method because that isn't less tricky.
static INPUT input[2] =
{
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0},
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0}
};
static bool init = true;
if (init)
{
init = false;
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
input[0].ki = keyDown;
input[1].ki = keyUp;
}
Regards, Alex
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
That is wrong as the parameters 2 - 5 get assigned to struct MOUSEINPUT and not to KEYINPUT, thus values like KEYEVENTF_EXTENDEDKEY will not properly assigned to input[0].ki.dwFlags but to input[0].mi.mouseData which has the same storage as input[0].ki.time. Look at this code:
bool operator==(const KEYBDINPUT& k1, const KEYBDINPUT& k2)
{
return (k1.dwExtraInfo == k2.dwExtraInfo) &&
(k1.dwFlags == k2.dwFlags) &&
(k1.time == k2.time) &&
(k1.wScan == k2.wScan) &&
(k1.wVk == k2.wVk);
}
bool operator==(const INPUT& i1, const INPUT& i2)
{
return (i1.type == i2.type) && (i1.ki == i2.ki);
}
void g()
{
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
INPUT input[2];
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki = keyDown;
input[1].ki = keyUp;
INPUT inputx[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
bool b1 = (input[0] == inputx[0]); // b1 = false;
bool b2 = (input[1] == inputx[1]); // b2 = false;
}
You may 'fix' the problem using this:
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY, 0, 0, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0, 0, 0}
};
Now KEYBDINPUT is correct as the first two members of KEYBDINPUT have WORD type and third is a DWORD whereas MOUSEINPUT starts with two LONG members. The two WORD members get mapped to the first LONG, and the DWORD get mapped to second LONG.
However, i would use the assign method because that isn't less tricky.
static INPUT input[2] =
{
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0},
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0}
};
static bool init = true;
if (init)
{
init = false;
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
input[0].ki = keyDown;
input[1].ki = keyUp;
}
Regards, Alex
ASKER
thanks alex... i see what is going on now.
unfortunately i have to have the declaration in the shared memory section if i want it to be global, because im using a GLOBAL windows hook. (i tested this out btw)
now i have 2 options:
1) putting the stuff in the shared memory section requires instalization at declaration, so i must assign the extra members of MOUSEINPUT to 0 (zero). This is nice and effecient, because the variables are only created and instalized once.
2) putting the stuff in the HookProc means i can use the assign method, but this will result in ineffeciency (due to creating and assigning new variables each time), and also expand 5 lines of code into about 15.
my final question is this:
does assigning the extra members of MOUSEINPUT to 0 (zero), decrease performance at all, or is it completly acceptable?
i.e. is this advisable to use with SendInput:
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY, 0, 0, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0, 0, 0}
};
cheers, suma
unfortunately i have to have the declaration in the shared memory section if i want it to be global, because im using a GLOBAL windows hook. (i tested this out btw)
now i have 2 options:
1) putting the stuff in the shared memory section requires instalization at declaration, so i must assign the extra members of MOUSEINPUT to 0 (zero). This is nice and effecient, because the variables are only created and instalized once.
2) putting the stuff in the HookProc means i can use the assign method, but this will result in ineffeciency (due to creating and assigning new variables each time), and also expand 5 lines of code into about 15.
my final question is this:
does assigning the extra members of MOUSEINPUT to 0 (zero), decrease performance at all, or is it completly acceptable?
i.e. is this advisable to use with SendInput:
static INPUT input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY, 0, 0, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0, 0, 0}
};
cheers, suma
Suma,
static member assignments wil be done only once. So with
static bool init = true;
if (init)
{
init = false;
// do something but only once
}
you are doing nothing that will harm performance. If you need shared memory just copy the well-defined structs from local memory to shared memory using memcpy.
static INPUT input[2] =
{
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0},
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0}
};
static bool init = true;
if (init)
{
init = false;
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
input[0].ki = keyDown;
input[1].ki = keyUp;
// Get the shared memory somehow
char* sharedMemoryPtr = createSharedMemory(...);
memcpy(sharedMemoryPtr, input, sizeof(input));
}
Hope, that helps
Alex
static member assignments wil be done only once. So with
static bool init = true;
if (init)
{
init = false;
// do something but only once
}
you are doing nothing that will harm performance. If you need shared memory just copy the well-defined structs from local memory to shared memory using memcpy.
static INPUT input[2] =
{
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0},
{INPUT_KEYBOARD, 0, 0, 0, 0, 0, 0}
};
static bool init = true;
if (init)
{
init = false;
KEYBDINPUT keyDown;
keyDown.dwExtraInfo = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY;
keyDown.time = 0;
keyDown.wScan = 0;
keyDown.wVk = VK_CAPITAL;
KEYBDINPUT keyUp;
keyUp.dwExtraInfo = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
keyUp.time = 0;
keyUp.wScan = 0;
keyUp.wVk = VK_CAPITAL;
input[0].ki = keyDown;
input[1].ki = keyUp;
// Get the shared memory somehow
char* sharedMemoryPtr = createSharedMemory(...);
memcpy(sharedMemoryPtr, input, sizeof(input));
}
Hope, that helps
Alex
da_mango_bros,
> >> unions dont have an order
>
> omg i never realized that... but can u explain why the code dosnt work then??
Just initialize it using an "undefined" state, as originally there is nothing in there and it's of no use to initialize your usion members with dummy data.
As soon as you get your first real data, you can set the values accordingly.
Stefan
> >> unions dont have an order
>
> omg i never realized that... but can u explain why the code dosnt work then??
Just initialize it using an "undefined" state, as originally there is nothing in there and it's of no use to initialize your usion members with dummy data.
As soon as you get your first real data, you can set the values accordingly.
Stefan
ASKER
so how do i instalize it undifined?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>>Wow you people.. I am disappointed. There is a pretty simple solution...
Good that you came to save us. I thought some others have already been mentioned.
Good that you came to save us. I thought some others have already been mentioned.
OK, here is another one, and the simplest yet:
change the stuct in the header file to
typedef struct tagINPUT {
DWORD type;
KEYBDINPUT ki;
} INPUT, *PINPUT;
Remove the union! The struct size/data is the same, it will NOT cause problems.
change the stuct in the header file to
typedef struct tagINPUT {
DWORD type;
KEYBDINPUT ki;
} INPUT, *PINPUT;
Remove the union! The struct size/data is the same, it will NOT cause problems.
ASKER
both of those solutions are exelent... ima use the class one because i prefer that.
sometimes there is an obvious solution but nobody can see it.
good stuff sitbon :)
sometimes there is an obvious solution but nobody can see it.
good stuff sitbon :)
ASKER
just to help out any1 else who is reading this thread because they have the same problem:
using a function to perform the instilization does not work if u want to have a two-dimensional array
i used a class:
class Init
{
public:
INPUT input[2];
Init()
{
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki.wVk = input[1].ki.wVk = VK_CAPITAL;
input[0].ki.wScan = input[1].ki.wScan = VK_CAPITAL;
input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
input[0].ki.time = input[1].ki.time = 0;
input[0].ki.dwExtraInfo = input[1].ki.dwExtraInfo = 0;
}
};
the actual instalization is performed here:
Init init;
then later on, in the HookProc:
SendInput(2, init.input, sizeof(INPUT));
thanks to every1 who participated in the thread, esp. alex (itsmeandnobodyelse) and sitbon
using a function to perform the instilization does not work if u want to have a two-dimensional array
i used a class:
class Init
{
public:
INPUT input[2];
Init()
{
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki.wVk = input[1].ki.wVk = VK_CAPITAL;
input[0].ki.wScan = input[1].ki.wScan = VK_CAPITAL;
input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
input[0].ki.time = input[1].ki.time = 0;
input[0].ki.dwExtraInfo = input[1].ki.dwExtraInfo = 0;
}
};
the actual instalization is performed here:
Init init;
then later on, in the HookProc:
SendInput(2, init.input, sizeof(INPUT));
thanks to every1 who participated in the thread, esp. alex (itsmeandnobodyelse) and sitbon
>> typedef struct tagINPUT {
>> DWORD type;
>> KEYBDINPUT ki;
>>} INPUT, *PINPUT;
Redefining the struct tagINPUT to overcome initialisation problems is a brilliant idea ... at the first glance. If you change the original header file that came with your compiler you always have to think on that if you get any update or change the development platform. Even worse it is to make the changes to a copy that got first int include order. There will come a time where your program doesn't work although you didn't change anything and you have no idea (anymore) where it come from.
To save the brilliance of the idea, i would suggest the following:
Define a new type using the struct definition above. Define your variables using the new struct and cast the type when using it as an argument:
typedef struct tagINPUTX {
DWORD type;
KEYBDINPUT ki;
} INPUTX, *PINPUTX;
INPUTX input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
....
SendInput(2, (PINPUT)input, sizeof(INPUTX));
Note, that sizeof(..) must use sizeof(INPUTX) as the new struct has a different size.
Regards, Alex
>> DWORD type;
>> KEYBDINPUT ki;
>>} INPUT, *PINPUT;
Redefining the struct tagINPUT to overcome initialisation problems is a brilliant idea ... at the first glance. If you change the original header file that came with your compiler you always have to think on that if you get any update or change the development platform. Even worse it is to make the changes to a copy that got first int include order. There will come a time where your program doesn't work although you didn't change anything and you have no idea (anymore) where it come from.
To save the brilliance of the idea, i would suggest the following:
Define a new type using the struct definition above. Define your variables using the new struct and cast the type when using it as an argument:
typedef struct tagINPUTX {
DWORD type;
KEYBDINPUT ki;
} INPUTX, *PINPUTX;
INPUTX input[2] =
{
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0},
{INPUT_KEYBOARD, VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}
};
....
SendInput(2, (PINPUT)input, sizeof(INPUTX));
Note, that sizeof(..) must use sizeof(INPUTX) as the new struct has a different size.
Regards, Alex
itsmeandnobodyelse, you're probably right, but the the point is this: if you change the header, compile your program, and say change it back, the only thing that would break it is re-arranging or changing the size of the INPUT struct... which is unlikely. I do agree that it it kind of a messy solution in a way, mainly in the sense of "what the hell did he do here?" when someone else reads it down the line :)
da mango - glad you liked my ideas :)
da mango - glad you liked my ideas :)
>> the only thing that would break it is re-arranging or changing the size of the INPUT struct... which is unlikely
No, much more likely he will get a new version of the compiler thus overwriting the changes, recompile the project - not remembering that there is a header that must be changed. If there are some years between there is a good chance to overlook that. And what makes it worse is that it will compile without problems. Changing a standard header isn't a good idea as long as you have a cheap alternative.
>> the only thing that would break it is re-arranging or changing the size of the INPUT
That is actually a minor problem as the size is an argument of SendInput.
Regards, Alex
No, much more likely he will get a new version of the compiler thus overwriting the changes, recompile the project - not remembering that there is a header that must be changed. If there are some years between there is a good chance to overlook that. And what makes it worse is that it will compile without problems. Changing a standard header isn't a good idea as long as you have a cheap alternative.
>> the only thing that would break it is re-arranging or changing the size of the INPUT
That is actually a minor problem as the size is an argument of SendInput.
Regards, Alex
I don't think you really get what I'm saying, but that's ok because the question is answered. It's obvious that changing the header causes those issues.
> But first union member is MOUSEINPUT mi, so this becomes very hard.
do something like:
switch(type){
case INPUT_MOUSE:
/* Display mouse data mi.* */
break;
case INPUT_KEYBOARD:
/* Display keyboard data ki.* */
break;
case INPUT_HARDWARE:
/* Display hardware data hi.* */
break;
default:
/* Error */
}
Cheers,
Stefan