C / C ++ - Windows - как отслеживать данные контекста HWND - PullRequest
1 голос
/ 24 ноября 2010

Предположим, что в Windows открыто несколько окон (HWND) одного и того же класса окон. Как вы отслеживаете данные контекста в оконной процедуре, чтобы, например, окно 1 не изменялось, когда пользователь пытался набрать в окне 2?

CreateWindow () не возвращается до тех пор, пока WndProc () не будет вызван несколько раз, поэтому вы не можете просто установить результирующий HWND для данных контекста и выполнить поиск в WndProc (); вам нужно установить его в WndProc ().

WndProc () напрямую не передает контекстную информацию, кроме сообщений о создании окна, но, к сожалению, сообщения о создании окна не совсем первые сообщения, которые передаются в WndProc (). Нет, я нахожу такие вещи, как WM_SIZE, WM_NCSIZE и даже некоторые другие, переданные прежде, чем я когда-либо увижу WM_CREATE.

Хранение HWND в механизме хранения связанного списка будет неэффективным при большом количестве окон: каждый элемент управления в окне - это просто другой тип окна и, следовательно, другой HWND, который необходимо отслеживать; после нескольких сотен элементов управления поиск связанного списка для HWND станет основным узким местом в программе после того, как несколько десятков сообщений будут переданы в программу за короткий промежуток времени!

Из того, что я слышал, некоторые люди используют SetWindowLong () - но я также слышал, что некоторым библиотекам нравится использовать это тоже для хранения своей собственной контекстной информации отдельно от программы, и что иногда могут происходить конфликты данных окна. Как этого можно избежать?

Ответы [ 4 ]

4 голосов
/ 24 ноября 2010

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

// ...
m_hWnd = CreateWindowEx(0,"Classname","Title",WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,CW_USEDEFAULT,
                        320,200,NULL,NULL,hInstance, /*the magic pointer*/ this);

// ...

if(uMsg == WM_CREATE)
{
    // collected here..
    pParent = (CWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
    // .. and then stored for later lookup
    SetWindowLongPtr(hWnd,GWL_USERDATA,(LONG_PTR)pParent); 
}
// ...

Вы также можете поймать сообщение WM_NCCREATE, как предложено Му-сок .
И я не думаю, что вам следует беспокоиться о сообщениях до WM_CREATE, потому что окно даже не полностью инициализировано в этот момент. Если вам нужно установить текст, вы делаете это после вызова на CreateWindow(Ex), будь то пользовательский ввод или SendMessage вызов.

2 голосов
/ 24 ноября 2010

Тот, кто создает окно, владеет этим окном на 100%. Если вы тот, кто вызывает CreateWindow (), то вы можете использовать GetWindowLong, зная, что он ваш.

Однако, если библиотека создает окно, вы не можете, потому что оно не ваше.

(Кроме того: ничто не мешает никому наступать на чьи-то пальцы, но соглашение довольно стандартно).

Если вы используете библиотеку, которая делает это, у нее, как правило, будет какой-то механизм для связи ваших собственных данных с окном. Конечно, вам нужно будет обратиться к документации для этого.

1 голос
/ 25 ноября 2010

Использовать свойства Windows: SetProp( HWND ,... ), Getprop( HWND ,... ) и RemoveProp( HWND ,... )

0 голосов
/ 24 ноября 2010

Разве вы не можете использовать WNDCLASS.cbWndExtra, чтобы объявить, какое личное хранилище нужно вашему классу, и тогда оно будет выделяться Windows всякий раз, когда он создает окно этого класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...