Разыменование указателя C++

Мне только что удалось написать глобальный хук CBT на С++, который можно использовать с С#. Это может звучать глупо, но я очень плохо разбираюсь в указателях и их разыменовании из-за моей работы с С#.

Я не могу разыменовать указатель внутри структуры, на которую указывает lParam.

Это выглядит так: lParam — это длинный указатель на структуру CBT_CREATEWND, которая, в свою очередь, содержит элемент «lpcs» и указатель на CREATESTRUCT. Эта структура содержит член "x", который я хочу прочитать. Я пробовал следующее, но получаю недопустимые значения для x:

CREATESTRUCT str = *(LPCREATESTRUCT)(((LPCBT_CREATEWND)lParam)->lpcs);
int normal = str.x;
PostMessage(FindWindow(NULL, L"Process Watcher Window"), RegisterWindowMessage(L"ALEXX_SEINE_WNDMESSAGE_C"), wParam, normal);

может кто-нибудь, пожалуйста, помогите мне?


person alex    schedule 18.01.2011    source источник
comment
Часть разыменования выглядит нормально. вы уверены, что правильно вызывали функции API для получения значений?   -  person Andrey    schedule 18.01.2011
comment
Нельзя ли сделать так: LPCREATESTRUCT str = (LPCREATESTRUCT)(((LPCBT_CREATEWND)lParam)->lpcs); за которым следует int normal = str-›x;   -  person Michael Smith    schedule 18.01.2011
comment
@Michael: (LPCREATESTRUCT) актерский состав не нужен. lpcs уже имеет тип LPCREATESTRUCT.   -  person Nawaz    schedule 18.01.2011


Ответы (2)


Ваш синтаксис, похоже, проверен, хотя он, возможно, немного нечитаем, и приведение LPCREATESTRUCT явно не нужно.

Вы упомянули, что получаете неверные значения для x, возможно, lParam на самом деле не является указателем на структуру CBT_CREATEWND? Проверяете ли вы, что nCode функции обратного вызова равно HCBT_CREATEWND перед приведением lParam?

person Skyler    schedule 18.01.2011
comment
Итак, какие значения вы получаете для x? Является ли значение недопустимым, но всегда одинаковым? Можете ли вы привести примеры? Я полагаю, что я как бы превращаю это в вопрос Win32, а не об указателях, но ясно, что это не проблема разыменования. - person Skyler; 18.01.2011
comment
Хорошо, например, я получаю -2147483648 (или что-то подобное) каждый раз, когда создается окно! - person alex; 18.01.2011
comment
#define CW_USEDEFAULT 0x80000000, то есть -2147483648, если тип LPARAM (длинный, 32-разрядный). Значение правильное, и ваш код в порядке. См. CreateWindowEx документацию по параметру x. - person Skyler; 18.01.2011
comment
что означает использование по умолчанию? поэтому я должен читать lParam в С# как UIntPtr? а то у меня CW_USEDEFAULT, а какая тогда позиция окна?? - person alex; 18.01.2011
comment
Откройте кучу окон проводника, не перемещая ни одно из них. Они автоматически позиционируются системой, поскольку они были инициализированы с помощью CW_USEDEFAULT в качестве параметра x/y для CreateWindowEx. Если вам нужно получить положение окна, вы можете сделать это позже в вашей программе, после обработки сообщения ALEXX_SEINE_WNDMESSAGE_C. - person Skyler; 18.01.2011
comment
но я хочу расположить окно изначально с левой стороны за пределами рабочего стола, поэтому я установил для члена x значение -cx, но окно все еще остается там, где оно было! Как я могу получить положение, в котором должно быть окно, прежде чем оно будет показано? - person alex; 18.01.2011
comment
Согласно вашему исходному сообщению, вы разыменовываете указатель на структуру. Во-первых, вы должны сделать так, как предложил Эван Теран, и поддерживать указатель на структуру. Затем вы можете сделать что-то вроде str->x = -str->cx;. Если это не сработает, вы можете использовать SetWindowPos, используя HWND, который вы берете в крючок. - person Skyler; 18.01.2011
comment
хорошо спасибо. И последний вопрос: я хочу переместить окно туда, где оно должно было быть через пару секунд, но как я могу узнать, куда его поместить, когда его значение X было 0x80000000? - person alex; 18.01.2011
comment
Я никогда не знал, как именно работает CreateWindowEx с CW_USEDEFAULT, но вы можете попробовать использовать GetWindowRect после полной инициализации окна. Затем SetWindowPos, чтобы установить нужную позицию... затем снова SetWindowPos после задержки. Я сообщу вам здесь, если найду более элегантное решение. - person Skyler; 18.01.2011
comment
Большое спасибо, Скайлер. Знаете ли вы, как я могу запустить GetWindowRect сразу после инициализации окна, чтобы оно не всплывало на экране, а затем исчезало? - person alex; 18.01.2011
comment
Почему окно исчезает в первую очередь? В любом случае, вы можете использовать свой хук для обработки HCBT_MOVESIZE, который должен быть отправлен сразу после HCBT_CREATEWND. - person Skyler; 18.01.2011
comment
Хм, это хорошая идея, я мог бы просто подождать, пока HCBT_MOVESIZE не будет поднят с моим дескриптором окна. Я проверю это. еще раз, спасибо за вашу помощь и терпение со мной :) - person alex; 18.01.2011
comment
Абсолютно. Будьте осторожны и не стесняйтесь публиковать здесь, если вам нужна дополнительная помощь. - person Skyler; 18.01.2011
comment
У меня проблема: после вызова хука HCBT_CREATEWND Windows не вызывает хук HCBT_MOVESIZE! Что мне теперь делать? Возможно, установите таймер с интервалом 10 мс, чтобы получить позицию с GetWindowRect - person alex; 18.01.2011
comment
Последнее предложение, которое у меня есть, это попробовать подключиться к HCBT_ACTIVATE... Возможно, это сработает. Не похоже, что есть хороший способ сделать это. - person Skyler; 18.01.2011
comment
Да, HCBT_ACTIVATE действительно срабатывает сразу после HCBT_CREATEWND, а с GetWindowRect я могу получить исходное положение окон! Большое спасибо, Скайлер. - person alex; 19.01.2011

Ну, я не могу говорить о мелких деталях того, почему вы получаете недопустимые значения x, но я бы, вероятно, написал этот код по-другому:

// the way you had it, it was making a copy of the CREATESTRUCT and storing it in str
// this just uses a pointer
LPCREATESTRUCT str = ((LPCBT_CREATEWND)lParam)->lpcs;
// when you have a pointer, use -> to use a member
int normal = str->x;

Поскольку вы сказали, что новичок в использовании указателей, я немного поясню ->. Когда вы пишете x->y, это действительно то же самое, что и (*x).y, но с более приятным синтаксисом.

Также совет, хотя приведения в этом коде кажутся разумными. В общем, если вы обнаружите, что много забрасываете, вы, вероятно, делаете это либо трудным путем, либо неправильным путем. Так что убедитесь, что вы нашли время, чтобы понять любые броски, которые вы делаете.

person Evan Teran    schedule 18.01.2011
comment
Смотрите мои правки. Может быть, последняя строка вызывает отправку неправильного значения в мою программу на С#? - person alex; 18.01.2011
comment
Является ли HWND, о котором вы пытаетесь получить информацию, другим процессом или чем-то еще? - person Evan Teran; 18.01.2011