Blog. Just Blog

Образ мышления: Assembler

То, что не удается запрограммировать на Ассемблере, приходится паять
Образ мышления: Assembler - RSS-канал Образ мышления: Assembler - Карта сайта

Как изменить цвет кнопок диалогового окна

17.11.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
Когда-то давно в одной из статей я рассказывал, как менять цвета различных элементов диалоговых окон Windows. Наверняка вы обратили внимание, что элемент типа BUTTON, то есть кнопка, выбивается из общей схемы и на изменение цвета не реагирует должным образом. Решить эту проблему все-таки можно, но для этого придется самостоятельно отрисовывать все компоненты кнопки - фон, рамку и надпись. Зато такой способ открывает неограниченные возможности по кастомизации кнопок.

Первым делом в ресурсах или в функции создания кнопки через CreateWindow(Ex) надо дополнить стиль модифицируемой кнопки параметром BS_OWNERDRAW. С этого момента все функции по рисованию перекладываются на наше приложение. Для этого приложение должно обрабатывать сообщение WM_DRAWITEM. Окну-владельцу кнопки в параметре lParam этого сообщения передается указатель на структуру DRAWITEMSTRUCT, на основании которой мы и будем заниматься рисованием.
  1.         cmp     [msg],WM_DRAWITEM
  2.         je      color_button
  3.         ...
  4.         ...
  5. color_button:
  6.         ; Указатель на структуру DRAWITEMSTRUCT
  7.         mov     ebx,[lparam]
  8.  
  9.         ; Установить режим смешивания фоновых цветов
  10.         invoke  SetBkMode,[ebx+DRAWITEMSTRUCT.hDC],TRANSPARENT
  11.  
  12.         ; Кнопка активна?
  13.         test    [ebx+DRAWITEMSTRUCT.itemState],ODS_SELECTED
  14.         jz      @f
  15.  
  16.         invoke  GetSysColor,COLOR_ACTIVEBORDER
  17.         invoke  CreatePen,PS_SOLID,1,eax
  18.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  19.  
  20.         invoke  GetSysColor,COLOR_3DLIGHT
  21.         invoke  CreateSolidBrush,eax
  22.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  23.  
  24.         ; Прямоугольник с заливкой
  25.         invoke  Rectangle,[ebx+DRAWITEMSTRUCT.hDC],\
  26.                 [ebx+DRAWITEMSTRUCT.rcItem.left],\
  27.                 [ebx+DRAWITEMSTRUCT.rcItem.top],\
  28.                 [ebx+DRAWITEMSTRUCT.rcItem.right],\
  29.                 [ebx+DRAWITEMSTRUCT.rcItem.bottom]
  30.  
  31.         jmp     loc_text
  32. @@:
  33.         ; Установить цвет и стиль рамки
  34.         invoke  GetSysColor,COLOR_3DDKSHADOW
  35.         invoke  CreatePen,PS_SOLID,3,eax
  36.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  37.  
  38.         ; Установить цвет фона
  39.         invoke  GetSysColor,COLOR_HIGHLIGHT
  40.         invoke  CreateSolidBrush,eax
  41.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  42.  
  43.         ; Прямоугольник с заливкой
  44.         invoke  Rectangle,[ebx+DRAWITEMSTRUCT.hDC],\
  45.                 [ebx+DRAWITEMSTRUCT.rcItem.left],\
  46.                 [ebx+DRAWITEMSTRUCT.rcItem.top],\
  47.                 [ebx+DRAWITEMSTRUCT.rcItem.right],\
  48.                 [ebx+DRAWITEMSTRUCT.rcItem.bottom]
  49.  
  50. loc_text:
  51.         ; Длина надписи на кнопке
  52.         invoke  GetWindowTextLength,[ebx+DRAWITEMSTRUCT.hwndItem]
  53.         inc     eax
  54.         mov     [len],eax
  55.         invoke  GetWindowText,[ebx+DRAWITEMSTRUCT.hwndItem],buff,[len]
  56.  
  57.         ; Установить цвет текста
  58.         invoke  SetTextColor,[ebx+DRAWITEMSTRUCT.hDC],0x0000FFFF
  59.  
  60.         ; Для нажатой кнопки сдвинуть текст вниз-вправо
  61.         test    [ebx+DRAWITEMSTRUCT.itemState],ODS_SELECTED
  62.         jz      @f
  63.  
  64.         ; Установить цвет текста
  65.         invoke  SetTextColor,[ebx+DRAWITEMSTRUCT.hDC],0x000000FF
  66.  
  67.         add     [ebx+DRAWITEMSTRUCT.rcItem.left],2
  68.         add     [ebx+DRAWITEMSTRUCT.rcItem.top],2
  69. @@:
  70.         ; Надпись на кнопке
  71.         lea     esi,[ebx+DRAWITEMSTRUCT.rcItem]
  72.         invoke  DrawText,[ebx+DRAWITEMSTRUCT.hDC],buff,[len],esi,\
  73.                 DT_SINGLELINE+DT_VCENTER+DT_CENTER
В зависимости от состояния кнопки, нажата она или нет, меняется цвет фона, цвет текста и стиль рамки. Здесь рамка нарисована единым цветом и толщиной, но при необходимости можно заморочиться и нарисовать "трехмерные" границы с помощью функций MoveToEx и LineTo. Еще было бы правильным проверять, что цвета меняются именно для нужной кнопки, делается это проверкой элемента itemID в структуре DRAWITEMSTRUCT. В приведенном примере я это осознанно пропустил, чтобы не загромождать код.

Читать статью целиком »
Просмотров: 279 | Комментариев: 0

Получение данных из консольного окна другого приложения

02.11.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
Мы уже умеем перехватывать ввод и вывод консольных приложений, но этот способ работает только для тех процессов, которые мы сами запустили. Но иногда надо получать информацию из консольных приложений, которые уже были запущены в системе или могут быть запущены в дальнейшем, но не нами. А еще бывают консольные приложения, вывод которых невозможно перенаправить и, соответственно, невозможно получить описанным ранее способом. Для них также придется использовать способ из этой статьи.

Для начала как всегда несколько структур, которые изначально не описаны в FASM. Они нам понадобятся для работы с консольным окном:
  1. struct  COORD
  2.         X dw ?
  3.         Y dw ?
  4. ends
  5.  
  6. struct  SMALL_RECT
  7.         Left   dw ?
  8.         Top    dw ?
  9.         Right  dw ?
  10.         Bottom dw ?
  11. ends
  12.  
  13. struct CONSOLE_SCREEN_BUFFER_INFO
  14.         dwSize              COORD
  15.         dwCursorPosition    COORD
  16.         wAttributes         dw ?
  17.         srWindow            SMALL_RECT
  18.         dwMaximumWindowSize COORD
  19. ends
Теперь немного теории. Любое приложение, даже GUI, может создать собственную консоль или приаттачиться к уже существующей. Для аттача достаточно знать только идентификатор консольного процесса. После этого получаем стандартный хэндл вывода, используемый в этой консоли, параметры консольного окна (количество строк и столбцов), а потом единственной функцией ReadConsoleOutputCharacter забираем из консольного окна все содержимое.

Читать статью целиком »
Просмотров: 143 | Комментариев: 0

Как получить реальную версию Windows из режима совместимости

25.09.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

Как получить реальную версию Windows из режима совместимости

Одной из основных политик компании Microsoft является поддержка обратной совместимости программ, то есть программы для Windows, написанные даже очень давно, теоретически должны работать на современных системах. Один из механизмов обеспечения такой работоспособности - запуск программ в режиме совместимости. Достаточно в свойствах исполняемого файла указать, какую версию Windows надо использовать, и система при запуске программы будет эмулировать для нее окружение именно этой версии. Если при этом из программы попытаться получить версию Windows при помощи функции GetVersion, GetVersionEx или даже RtlGetVersion, то результат вернет версию эмулируемой ОС. А можно ли как-то определить, что программа запущена в режиме совместимости и получить реальную версию Windows, на которой она работает? Можно!

Читать статью целиком »
Просмотров: 954 | Комментариев: 11

Особенности работы с контролом SysMonthCal32

07.09.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

Различная ширина SysMonthCal32 в разных локалях

При разработке одной из своих программ я столкнулся с интересной ситуацией. Никаких ракетных технологий, просто в диалоговом окне выводится стандартный виджет календарика через контрол SysMonthCal32. Я работаю в русской версии Windows и наивно предположил, что размеры виджета календарика всегда должны как-то вписываться в те границы, которые я ему определил. Но, как вы можете видеть на этих скриншотах, ширина контрола с календариком заметно отличается в зависимости от установленной в системе локали, на что мне указал один из пользователей (Mufasa, спасибо!). Вариантов нет, пришлось изучить этот вопрос.

Читать статью целиком »
Просмотров: 387 | Комментариев: 2

Как узнать загруженность процессора

24.08.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

Как узнать загруженность процессора

Очередная интересная задача для программирования - узнать загруженность центрального процессора компьютера в процентах. Проблема в том, что система ни через какие API не предоставляет такого значения, как "загруженность", его просто нет. Зато есть хорошая функция GetSystemTimes, которая возвращает три значения: время, которое система бездействовала, время работы системы в режиме ядра и время работы системы в пользовательском режиме. Узнав разницу значений между этими таймингами за определенный интервал, можно определить загруженность процессора за этот интервал. На многоядерных системах эта функция возвращает суммарные значения по всем ядрам.

Читать статью целиком »
Просмотров: 666 | Комментариев: 7

prev 01 02 03 04 05 06 07 08 09 ... 33 next
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2018
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0016 сек.) / Память: 4.75 Mb
Наверх