Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 |

 

  Вопрос: Актуальность hWnd Добавлено: 26.02.06 13:16  

Автор вопроса:  mc-black | Web-сайт: mc-black.narod.ru/dzp.htm | ICQ: 308-534-060 
Изменяется ли hWnd окна после его создания?

В циклах создаю много контролов через CreateWindowEx, возвращаемый ими результат (hWnd) сохраняю в массив. Потом когда мне надо убрать их с главного окна я прохожусь по массиву и удаляю через DestroyWindow. Но удаляется около половины контролов.. Местами возвращается ошибка Invalide Handle - они-то и остаются целыми. Такое чувство, что hWnd некоторых окон может поменяться при UpdateWindow или ещё где-то.. Как мне заполнить массив актуальными hWnd?

P.S. Код мне не нужен, делаю в MASM32, нужны практические советы..

Ответить

  Ответы Всего ответов: 16  

Номер ответа: 1
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #1 Добавлено: 26.02.06 13:32
Изменяется ли hWnd окна после его создания?

Нет.

Многопоточность юзаешь?

Ответить

Номер ответа: 2
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #2 Добавлено: 26.02.06 13:57
Возможно, твой код получает доступ к массиву в результате ошибки и модифицирует его содержимое.
Другое вряд ли что может быть.

Ответить

Номер ответа: 3
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #3 Добавлено: 26.02.06 14:01
Либо с адресацией что-то не так.
Выкладывай в debug.print хэндлы при создании и при удалении окон. И проверь наличие удаляемых хэндлов в списке созданных. Если удаляемых хэндлов нет в списке созданных - значит код запортил массив.

Ответить

Номер ответа: 4
Автор ответа:
 mc-black



ICQ: 308-534-060 

Вопросов: 20
Ответов: 1860
 Web-сайт: mc-black.narod.ru/dzp.htm
 Профиль | | #4
Добавлено: 26.02.06 16:58
1. Многопоточность пока нет.
2.
Возможно, твой код получает доступ к массиву в результате ошибки и модифицирует его содержимое.

этого я больше всего и боялся, возможно, что да..
3.
Мой массив в стеке, он создается перемещением esp вне процедур, т.е. "в глобальном контексте".. или если я не позаботился сохранять регистры общего назначения перед вызовами api, а они их модифицируют в циклах при создании контролов.

И проверь наличие удаляемых хэндлов в списке созданных


IsWindow - проверял, нет таких :)

Самое смешное, при удалении не удаляются контролы строго по какому-то закону, почти по диагонали.. немного врассыпную. Каждый раз одинаково.

Ответить

Номер ответа: 5
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #5 Добавлено: 26.02.06 18:44
В стеке такие вещи не держат. При выходе из процедуры в которой инициализировался массив, сохранность содержимого стека не гарантируется. Т.е. винда область стека, в которой размещен массив, может передать под стек в любую процедуру, и твой массив будет затерт параметрами этой процедуры или её локальными переменными.
Выдели память virtualalloc и там держи свой массив.

Ответить

Номер ответа: 6
Автор ответа:
 mc-black



ICQ: 308-534-060 

Вопросов: 20
Ответов: 1860
 Web-сайт: mc-black.narod.ru/dzp.htm
 Профиль | | #6
Добавлено: 26.02.06 19:40
HOOLIGAN
, спасибо, может подробнее подскажешь, как мне потом этот кусок можно будет использовать? Как обращаться к чему-то внутри него, как изменить размер (увеличить, уменьшить), если это возможно?

А про всё, что ты сказал, я хорошо знаю и понимаю. Просто по-другому пока не додумался. Массив у меня не затрётся (мой частный случай), т.к. он вне всех процедур объявляется. Ошибку я свою нашёл и исправил, сейчас всё хорошо. Стыдно сказать, массив неправильно заполнял, поэтому по нескольку hWnd в одно место лепил.. Сейчас всё работает. По основной теме - спасибо за внимание!

Ответить

Номер ответа: 7
Автор ответа:
 mc-black



ICQ: 308-534-060 

Вопросов: 20
Ответов: 1860
 Web-сайт: mc-black.narod.ru/dzp.htm
 Профиль | | #7
Добавлено: 26.02.06 19:41
Извиняюсь за неаккуратное и неправильное использование псевдотэгов, надо было BOLD.

Ответить

Номер ответа: 8
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #8 Добавлено: 26.02.06 20:37
Ну пользоваться массивом очень просто :)


.data?
    pArray    dd ?

.code
        ';инициализация массива размером на 256 hWnd'ов :)
        invoke  VirtualAlloc, NULL, 1024, MEM_COMMIT, PAGE_READWRITE
        mov     pArray,eax              ';сохраняем адрес массива в глобальной переменной
        ';заполнение массива числами от 0 до 255
        mov     ecx,255
        @@:
        mov     dword ptr[eax+ecx*4],ecx
        dec     ecx
        jns     @B
        
        ';читаем массив задом наперед - от последнего элемента(index==255) к первому (index==0)
        mov     ecx, 255
        mov     eax,pArray              ';адрес нулевого элемента массива
        @@:
        PrintDec dword ptr[eax+ecx*4]   ';размер элемента - 4 байта, поэтому индекс*4
        dec     ecx
        jns     @B
        
        ';освобождение массива
        invoke  VirtualFree, pArray, 0, MEM_RELEASE


  ';№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№
  ';второй вариант - с отдельными ф-циями записи и чтения из массива
';==================================================================================
SetArrayElement proc lpArray:DWORD, dwIndex:DWORD, ElementValue:DWORD
    option prologue : none
    option epilogue : none
    mov     eax,[esp+4]
    mov     ecx,[esp+8]
    mov     edx,[esp+12]
    mov     [eax+ecx*4],edx
    retn    12
    option prologue : prologuedef
    option epilogue : epiloguedef
SetArrayElement endp

';==================================================================================
GetArrayElement proc lpArray:DWORD, dwIndex:DWORD
    option prologue : none
    option epilogue : none
    mov     edx,[esp+4]
    mov     ecx,[esp+8]
    mov     eax,[edx+ecx*4]
    retn    8
    option prologue : prologuedef
    option epilogue : epiloguedef
GetArrayElement endp

        ';
        ';инициализация массива размером на 256 hWnd'ов :)
        invoke  VirtualAlloc, NULL, 1024, MEM_COMMIT, PAGE_READWRITE
        mov     pArray,eax              ';сохраняем адрес массива в глобальной переменной
        ';заполнение массива числами от 0 до 255
        push    ebx
        mov     ebx,255
        @@:
        invoke  SetArrayElement, pArray, ebx, ebx
        dec     ebx
        jns     @B
        pop     ebx
        
        ';читаем массив задом наперед - от последнего элемента(index==255) к первому (index==0)
        push    ebx
        mov     ebx, 255
        @@:
        invoke  GetArrayElement,pArray,ebx
        PrintDec eax                    ';размер элемента - 4 байта, поэтому индекс*4
        dec     ebx
        jns     @B
        pop     ebx
        
        ';освобождение массива
        invoke  VirtualFree, pArray, 0, MEM_RELEASE


Чтобы растянуть массив - нужно пересчитать его размер под новое количество элементов, выделить новый кусок памяти, скопировать в него старый массив, и затем старый удалить.
Можно ещё написать две небольшие служебные ф-ции типа RedimArray, в которой растягивать/уменьшать размер массива, и InitArray, в которую вынести VirtualAlloc и VirtualFree.
В довершение всего оформить эти 4 ф-ции в отдельный .inc - и у тебя полноценный массив с ф-циями инициализации, удаления, изменения размерности, чтения и записи в массив.
Все :)

Ответить

Номер ответа: 9
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #9
Добавлено: 26.02.06 23:52
Что-то ты хулиган тут намудрил :) Зачем использовать masm, точнее его синтаксис (proc) когда ты вытаскиваешь параметры через esp :))

Не люьишь обращаться к переданным параметрам по имени, или хотя бы по ebp регистру :) ?

ЗЫ
Дело вкуса, но я предпочитаю работать с Heap'ами, а не Virtal'aми...

Ответить

Номер ответа: 10
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #10 Добавлено: 27.02.06 00:55
Не в том дело, что не люблю по имени, просто функции коротенькие - в одной 5 инструкций - в другой -4, и на этом фоне если не предотвратить формирование стекового фрейма, то сразу добавятся бесполезные
push ebp
mov ebp,esp
leave
На фоне 4 инструкций - это очень много, особенно в плане скорости.
Так что тут все продумано :)
А синтаксис proc <parameters> использован чисто для визуального восприятия параметров.

HeapAlloc пару раз проглючил, уже не помню, что было - и я от него отказался. Опять же VirtualAlloc меньше кода :)

Ответить

Номер ответа: 11
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #11
Добавлено: 27.02.06 01:11
Вижу :) Все еще лишние такты да байты выискиваешь :))

Лично у мня к хипам никаких нареканий нет... К локалам есть :) Однажды случился глюк, использовал strlen из masmlib, так там для ускорения процесса в регистр махом забиралось двойное слово, а потом уже искался нулевой байт... Так случилось что выделилялось памяти не кратное 4-м число, и конец этой памяти аккурат приходился на конец страницы :) В итоге при попытке забрать лишние 1-3 байта, вылетало нарушение доступа... Обидная обшибка была...

Ответить

Номер ответа: 12
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #12 Добавлено: 27.02.06 01:12
В принципе можно сделать ещё короче и быстрее, оформив функции как макросы, и избавиться от call/ret

GetArrayElement MACRO p_arr, index
    mov     eax,p_arr
    mov     ecx,index
    mov     eax,[eax+ecx*4]
GetArrayElement ENDM

    'и вызывать
    GetArrayElement pArray, 123

Ответить

Номер ответа: 13
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #13 Добавлено: 27.02.06 01:20
о StrLen: более грамотная реализация этого метода (подвордное чтение) сделана в си-шной strlen.
Там читается с адресов, кратных 4. Т.е. первые 0-3 байта читаются побайтно, а начиная с первого кратного 4 адреса - подвордно. И на граблю не наступишь, и скорость повышается за счет кратности читаемого адреса четырем.

Ответить

Номер ответа: 14
Автор ответа:
 mc-black



ICQ: 308-534-060 

Вопросов: 20
Ответов: 1860
 Web-сайт: mc-black.narod.ru/dzp.htm
 Профиль | | #14
Добавлено: 27.02.06 12:27
Во какая интересная дискуссия получилась! Всё (почти) понятно, интересно, полезно.. sne, а твой примерчик можно с HeapAlloc? И чем всё-таки он хуже/лучше?

Ответить

Номер ответа: 15
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #15
Добавлено: 27.02.06 21:33
Дело вкуса, но я предпочитаю работать с Heap'ами, а не Virtal'aми...

Повторюсь, дело вкуса и привычки :)

Можно кста несколько хипов создать, не знаю где это может понадобиться, мне и одного процессового хватало :) Но тем-ни менее :))

А что там с хипами пример-то, просто выделение памяти другой функцией, а так, весь выше приведенный код справедлив для любого способа и от способа выделения памяти ни коим место м не зависит :)) лишь бы она была...

ЗЫ
Виртуалы выделяют память страницами, хеап-ы - сколько укажешь... с одной стороны :) как видит пользователь, хотя на самом деле резервируется страница :)

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам