Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный хостинг на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 1913
∙ повысить рейтинг »
_Ayl_
Статус: Практикант
Рейтинг: 1839
∙ повысить рейтинг »
vladisslav
Статус: 5-й класс
Рейтинг: 1123
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Программирование / Assembler (Ассемблер)

Номер выпуска:1318
Дата выхода:02.04.2010, 20:00
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:416 / 71
Вопросов / ответов:1 / 1
IRC-канал по теме:#assembler

Вопрос № 177425: Добрового времени суток! Нужна помощь в написании программы. Задание: разработать на ассемблере простую программу, содержащую переключаемые страницы (достаточно двух) на одну поставить поле Memo, на вторую организовать вывод в ко...



Вопрос № 177425:

Добрового времени суток! Нужна помощь в написании программы.

Задание: разработать на ассемблере простую программу, содержащую переключаемые страницы (достаточно двух) на одну поставить поле Memo, на вторую организовать вывод в контейнер точечного рисунка из файла. На каждой странице по нажатию правой кнопки появляется контекстное меню. Команды меню - открытие соответствующих файлов. Нужно выполнить на Microsoft ASM

Отправлен: 23.03.2010, 23:46
Вопрос задал: Klayd, Посетитель
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, Klayd.
Измененная программа вместе с файлом ресурсов с учетом новых требований
Все остальное в прикрепленном архиве.
Код:

.386 ;32-битный код
.model flat, stdcall ;модель памяти и соглашение о вызове параметров
option casemap :none ;различаем большие-малые буковки

; include files
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include \oleaut32.inc
include \masm32\include\msvcrt.inc
include \masm32\macros\macros.asm

; libraries
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\msvcrt.lib

; Прототипы функций
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
TopXY PROTO :DWORD,:DWORD
RegisterWinClass PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
MsgLoop PROTO
Main PROTO
GetFileName PROTO :DWORD,:DWORD,:DWORD,:DWORD
CalcSize PROTO :DWORD,:DWORD,:DWORD,:DWORD
KeyProcEdit PROTO :DWORD,:DWORD,:DWORD,:DWORD
SaveFile PROTO :DWORD

;коды используемых ресурсов
IDI_ICON equ 500
I DD_DLG1 equ 101
IDD_DLG2 equ 102
IDM_FILE equ 201
IDM_SAVE equ 202
IDC_TEXT equ 301
IDC_FILENAME equ 302

;флаг задания пиктограммы для propertysheet
; (в windows.inc флаг почему-то называется PSH_USEDWORD ...)
PSH_USEHICON equ 00000002h

.data

fChange dd 0 ;флаг изменения текста в редакторе
szHeader db 'Property',0 ;заголовок основного окна
szTextTXT db 'Файл TXT',0 ;строка меню для выбора текстового файла
szTextBMP db 'Файл BMP',0 ;строка меню для выбора графического файла
szFilterTXT db 'Текстовые Файлы (*.txt)',0,'*.txt',0,0 ;фильтр для выбора текстовых файлов
szFilterBMP db 'Графические Файлы (*.bmp)',0,'*.bmp',0,0;фильтр для выбора графическых файлов
szTitle db 'Введите имя открываемого файла',0 ;заголовок для диалога выбора файлов
szTitleSave db 'Введите имя сохраняемого файла',0 ;заголовок для диалога выбора файлов
szSave db 'Сохранить',0 ;пункт меню, если возможно сохранение
szMessage db "Файл изменен, сохранить?",0 ;сообщение, когда было изменение
szDefault db 'default.txt',0 ;имя файла по-умолчанию

.data?

hInstance dd ? ;описатель экземпляра процесса
CommandLine dd ? ;командная строка
hIcon dd ? ;описатель пиктограммы
hCursor dd ? ;описатель курсора
sWid dd ? ;ширина экрана
sHgt dd ? ;высота экрана
hWnd dd ? ;описатель главного окна приложения
hBitMap dd ? ;описатель растрового изображения
hMemDC dd ? ;описатель совместимого контекста устройства (DC)
pKeyDefProcEdit dd ? ;адрес предыдущей функции окна редактора
PSHeader PROPSHEETHEADERA <> ;заголовок PropertySheet
PSPages PROPSHEETPAGE <> ;страницы PropertySheet
PROPSHEETPAGE <>
rectBMP RECT <> ;координаты для вывода BMP в окне
sizeBMP POINT <> ;размер BMP
szNameTXT db 256 dup ( ?) ;для хранения текущего имени txt-файла
szNameBMP db 256 dup (?) ;для хранения текущего имени bmp-файла

.code

start:
mov hInstance, rv(GetModuleHandle, NULL) ;описатель экземпляра процесса
mov CommandLine, rv(GetCommandLine) ;командная строка
mov hIcon, rv(LoadIcon,hInstance,IDI_ICON) ;пиктограмма
mov hCursor, rv(LoadCursor,NULL,IDC_ARROW) ;курсор
mov sWid, rv(GetSystemMetrics,SM_CXSCREEN) ;ширина экрана
mov sHgt, rv(GetSystemMetrics,SM_CYSCREEN) ;высота экрана

call Main ;запускаем

invoke ExitProcess,eax ;завершаем процесс

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

Main proc

LOCAL Wwd:DWORD, \ ;ширина основного окна
Wht:DWORD, \ ;высота основного окна
Wtx:DWORD, \ ;X-координата начала окна
Wty:DWORD ;Y-координата начала окна

STRING szClassName,"PropertyDialog_Class" ;класс основного окна

invoke RegisterWinClass,ADDR WndProc,ADDR szClassName, ;регистрируем класс окна
hIcon,hCursor,COLOR_BTNFACE+1
;посчитаем координаты окна
mov Wwd, 300
mov Wht, 246
invoke TopXY,Wwd,sWid
mov Wtx, eax
invoke TopXY,Wht,sHgt
mov Wty, eax

;создаем основное окно
invoke CreateWindowEx,WS_EX_LEFT,
ADDR szClassName,
ADDR szHeader,
WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX,
Wtx,Wty,Wwd,Wht,
NULL,NULL,
hInstance,NULL
mov hWnd,eax ;сохраним описатель окна

invoke ShowWindow,hWnd, SW_SHOWNORMAL ;показать
invoke UpdateWindow,hWnd ;обновить

call MsgLoop ;основной цикл обработки сообщений
ret

Main endp

;регистрируем класс окна
RegisterWinClass proc lpWndProc:DWORD, lpClassName:DWORD,
Icon:DWORD, Cursor:DWORD, bCol or:DWORD

LOCAL wc:WNDCLASSEX

mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNCLIENT or \
CS_BYTEALIGNWINDOW
m2m wc.lpfnWndProc, lpWndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInstance
m2m wc.hbrBackground, bColor
mov wc.lpszMenuName, NULL
m2m wc.lpszClassName, lpClassName
m2m wc.hIcon, Icon
m2m wc.hCursor, Cursor
m2m wc.hIconSm, Icon

invoke RegisterClassEx, ADDR wc
ret

RegisterWinClass endp

;цикл обработки сообщений
MsgLoop proc uses esi edi

LOCAL msg:MSG

xor edi, edi ; clear EDI
lea esi, msg ; Structure address in ESI
jmp jumpin

StartLoop:
invoke TranslateMessage, esi
invoke DispatchMessage, esi
jumpin: invoke GetMessage,esi,edi,edi,edi
test eax, eax
jnz StartLoop

mov eax, msg.wParam
ret

MsgLoop endp

;функция основного окна
WndProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

Switch uMsg
Case WM_CREATE
call Properties ;создаем PropertySheet
;дальше пойдем только когда выйдем из propertysheet
invoke SendMessage,[hWin],WM_CLOSE,0,0 ;и сразу завершаемся
return 0

Case WM_DESTROY
.if [hMemDC] != 0
invoke DeleteDC, [hMemDC] ;освободим ресурсы, если надо
.endif
invoke PostQuitMessage,NULL
return 0

Endsw

invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret

WndProc endp

;вычисляем координату начала отрезка длины wDim, чтобы он был посередине отрезка длины sDim
TopXY proc wDim:DWORD, sDim:DWORD

mov eax, [esp+8]
sub eax, [esp+4]
shr eax, 1

ret 8

TopXY endp

;функция окна первого диалога pPropertySheet
PSDialog1 proc uses ebx esi edi, hwnd, uMsg, wParam, lParam
LOCAL po int:POINT, \ ;для вывода меню
dwCount:dword, \ ;младшее двойное слово длины файла
dwHigh:dword ;старшее двойное слово длины файла

mov eax, [uMsg]
cmp eax, WM_INITDIALOG
jz dlg1_initdialog
cmp eax, WM_NOTIFY
jz dlg1_notify
cmp eax, WM_RBUTTONDOWN
jz dlg1_rbuttondown
cmp eax, WM_COMMAND
jz dlg1_command
dlg1_ok:
xor eax, eax
ret

;в инициализации диалога сделаем subclassing процедуры окна редактора
;это необходимо, чтобы по правой кнопке мыши вызывалось наше меню, а не стандартное для
;редактора. Для этого перенаправим сообщение WM_RBUTTONDOWN родителю!
dlg1_initdialog:
invoke GetDlgItem, [hwnd], IDC_TEXT ;получим в eax описатель окна редактора
;установим новую функцию окна, с сохранением старой в переменной
mov [pKeyDefProcEdit], rv(SetWindowLong, eax, GWL_WNDPROC, offset KeyProcEdit)
jmp dlg1_ok

;отработка уведомления
dlg1_notify:
mov eax, [lParam]
cmp [(NMHDR PTR [ eax]).code], PSN_SETACTIVE ;страница стала активной
jz SetActive
cmp [(NMHDR PTR [eax]).code], PSN_APPLY ;нажата "ОК"
jz Apply
cmp [(NMHDR PTR [eax]).code], PSN_RESET ;нажата "Отмена"
jnz dlg1_ok
Reset:
;проверим, были ли изменения в редакторе
.if fChange == 1
;спросим, надо ли сохранять
invoke MessageBox, [hwnd], offset szMessage, offset szHeader, MB_YESNO
.if eax == IDYES
;если "да", то сохраняем
invoke SaveFile, [hwnd]
.endif
.endif
jmp dlg1_ok
Apply:
;проверим, были ли изменения в редакторе
.if fChange == 1
;сохраним
invoke SaveFile, [hwnd]
.endif
jmp dlg1_ok
;стали активными - запомним себя, как стартовую страницу
SetActive:
xor eax, eax ;номер нашей страницы
mov [PSHeader.nStartPage], eax
jmp dlg1_ok

;нажата правая кнопка мыши
dlg1_rbuttondown:
;формируем координаты точки, где выводить меню
movzx eax, word ptr l Param
mov [point.x], eax
movzx eax, word ptr lParam+2
sub eax, 14 ; чтобы было чуть выше
mov [point.y], eax
lea eax, point
invoke ClientToScreen,[hwnd], eax ;оконные координаты в экранные
mov ebx, rv(CreatePopupMenu) ;создаем меню
;добавляем пункт меню "файл TXT"
invoke AppendMenu, ebx, MF_ENABLED or MF_BYCOMMAND, IDM_FILE, offset szTextTXT
;если были изменения, то добавим еще один пункт: "сохранить"
.if [fChange] == 1
invoke AppendMenu, ebx, MF_ENABLED or MF_BYCOMMAND, IDM_SAVE, offset szSave
.endif
;выводим и ждем выбор
invoke TrackPopupMenu, ebx, TPM_CENTERALIGN or TPM_LEFTBUTTON, [point.x], [point.y], 0, [hwnd], 0
;уничтожаем меню
invoke DestroyMenu, ebx
jmp dlg1_ok

;сделан выбор в меню
dlg1_command:
;проверим уведомление об изменении в редакторе
.if word ptr [wParam+2] == EN_CHANGE
mov fChange, 1 ;пометим!

;выбор нового файла
.elseif wPara m == IDM_FILE
;проверим, надо ли сохранить старое содержимое
;было ли изменение?
.if fChange == 1
;спросим
invoke MessageBox, [hwnd], offset szMessage, offset szHeader, MB_YESNO
.if eax == IDYES
;сохраняем старое
invoke SaveFile, [hwnd]
.endif
.endif
;запросим имя TXT-файла
invoke GetFileName,offset szNameTXT,offset szFilterTXT,GetOpenFileName,offset szTitle
;что-то ввели?
.if eax != 0
;получим описатель GroupBox-а на странице диалога ("ободок")
invoke GetDlgItem, [hwnd], IDC_FILENAME
;выведем полное имя файла с путем
invoke SetWindowText, eax, offset szNameTXT
;открываем файл
mov ebx, rv(CreateFile,offset szNameTXT,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0)
;узнаем длину файла
mov [dwCount], rv(GetFileSize, ebx, ADDR dwHigh)
;резервируем память под содержимое файла
;в конце добавим 1 байт для завершающего нуля
lea edi, dwCount
mov eax, [edi]
inc eax
;esi - адрес буфера
mov esi, rv(GlobalAlloc, GMEM_FIXED, eax)
;читаем файл
;edi - адрес переменной с д линой
;ebx - описатеь файла
invoke ReadFile, ebx, esi, [edi], edi, 0
;закрываем файл
invoke CloseHandle, ebx
;читаем реальную длину файла
mov eax, [edi]
;завершим нулем
mov byte ptr [eax+esi], 0
;получим описатель Edit-а на странице диалога
invoke GetDlgItem, [hwnd], IDC_TEXT
;и выведем в него
invoke SetWindowText, eax, esi
;освободим память
invoke GlobalFree, esi
.endif

;сохранение файла (содержимое редактора точно изменено)
.elseif wParam == IDM_SAVE
invoke SaveFile, [hwnd]
.endif
jmp dlg1_ok
PSDialog1 endp

;функция окна второго диалога pPropertySheet
PSDialog2 proc uses ebx esi edi, hwnd, uMsg, wParam, lParam
LOCAL point:POINT, \ ;для вывода меню
ps:PAINTSTRUCT ;для рисования в окне в отработке WM_PAINT

mov eax, [uMsg]
cmp eax, WM_NOTIFY
jz dlg2_notify
cmp eax, WM_RBUTTONDOWN
jz dlg2_rbuttondown
cmp eax, WM_COMMAND
jz dlg2_co mmand
cmp eax, WM_PAINT
jz dlg2_paint
dlg2_ok:
xor eax, eax
ret

;стали активными - запомним себя, как стартовую страницу
dlg2_notify:
mov eax, [lParam]
cmp [(NMHDR ptr [eax]).code], PSN_SETACTIVE
jnz dlg2_ok
mov eax, 1 ;номер нашей страницы
mov [PSHeader.nStartPage], eax
jmp dlg2_ok

;нажата правая кнопка мыши
dlg2_rbuttondown:
;формируем координаты точки, где выводить меню
movzx eax, word ptr lParam
mov [point.x], eax
movzx eax, word ptr lParam+2
sub eax, 14 ; чтобы было чуть выше
mov [point.y], eax
lea eax, point
invoke ClientToScreen,[hwnd], eax ;оконные координаты в экранные
mov ebx, rv(CreatePopupMenu) ;создаем меню
;добавляем один пункт меню
invoke AppendMenu, ebx, MF_ENABLED or MF_BYCOMMAND, IDM_FILE, offset szTextBMP
;выводим и ждем выбор
invoke TrackPopupMenu, ebx, TPM_CENTERALIGN or TPM_LEFTBUTTON, [point.x], [point.y], 0, [hwnd], 0
;уничтожа ем меню
invoke DestroyMenu, ebx
jmp dlg2_ok

;сделан выбор в меню
dlg2_command:
;проверим код пункта меню
.if wParam == IDM_FILE
;запросим имя BMP-файла
invoke GetFileName,offset szNameBMP,offset szFilterBMP,GetOpenFileName,offset szTitle
;что-то ввели?
.if eax != 0
;получим описатель GroupBox-а на странице диалога ("ободок")
invoke GetDlgItem, [hwnd], IDC_FILENAME
;выведем полное имя файла с путем
invoke SetWindowText, eax, offset szNameBMP

;загрузим BMP-файл
mov hBitMap, rv(LoadImage,0, offset szNameBMP,IMAGE_BITMAP,0,0,LR_LOADFROMFILE)
;получилочь?
.if eax != 0
;посчитаем размеры
invoke CalcSize, eax, [hwnd], offset rectBMP, offset sizeBMP
;если не было, то создадим совместимый контекст
.if [hMemDC] == 0
mov edi, rv(GetDC, [hwnd])
mov [hMemDC], rv(CreateCompatibleDC,edi)
invoke ReleaseDC, [hwnd], edi
.endif
;если совместимый конт екст есть, то выберем в него наш BitMap
.if [hMemDC] != 0
invoke SelectObject, [hMemDC], [hBitMap]
;описатель больше не нужен
invoke DeleteObject, [hBitMap]
;перерисуем
invoke InvalidateRect,[hwnd],0,1
.endif
.endif
.endif
.endif
jmp dlg2_ok

;рисуем BitMap
dlg2_paint:
mov edi, rv(BeginPaint,[hwnd],ADDR ps) ;edi=hDC
.if [hMemDC] != 0 ;надо что-то рисовать?
;копируем с масштабированием из совместимого контекста в окно
invoke StretchBlt, edi, [rectBMP.left], [rectBMP.top], [rectBMP.right], \
[rectBMP.bottom], [hMemDC], 0, 0, [sizeBMP.x], [sizeBMP.y], SRCCOPY
.endif
invoke EndPaint, [hwnd], ADDR ps
jmp dlg2_ok
PSDialog2 endp

;считаем размеры и координаты изображения
; все числа подобраны эксперементально (чтобы было более-менее красиво )
CalcSize proc uses edi esi, hBmp:dword, hWin:HWND, pRect BMP:dword, pSizeBMP:dword
LOCAL BMap:BITMAP, rc:RECT
invoke GetObject, hBmp, size BITMAP, ADDR BMap ;узнаем размер картинки< br> invoke GetClientRect, [hWin], ADDR rc ; и размер окна

mov edi, [pRectBMP] ;адрес RECT
mov [(RECT ptr [edi]).left], 14 ;начальный X вывода
mov [(RECT ptr [edi]).top], 22 ;начальный Y вывода
mov eax, [rc.right]
sub eax, 28
mov [(RECT ptr [edi]).right], eax ;ширина области вывода
mov eax, [rc.bottom]
sub eax, 42
mov [(RECT ptr [edi]).bottom], eax ;высота области вывода

mov esi, [pSizeBMP] ;адрес POINT
m2m [(POINT ptr [esi]).x], [BMap.bmWidth] ;ширина картинки
m2m [(POINT ptr [esi]).y], [BMap.bmHeight] ;высота картинки

;все последующее для перерасчета размера области вывода, чтобы картинка
; пропорционально масштабировалась, т.е. пропорционально растягивалась/сжималась
; до ближайшей стороны области вывода.
;Если убрать, то картинка будет растягиваться/сжиматься в области непропорционально
mov eax, [(RECT ptr [edi]).right]
imul [(POINT ptr [esi]).y]
mov ecx, eax
mov eax, [(REC T ptr [edi]).bottom]
imul [(POINT ptr [esi]).x]
cmp eax, ecx
jz CSRet
jb CSWidth
mov eax, ecx
idiv [(POINT ptr [esi]).x]
mov [(RECT ptr [edi]).bottom], eax
jmp CSRet
CSWidth:
idiv [(POINT ptr [esi]).y]
mov [(RECT ptr [edi]).right], eax
CSRet:
ret
CalcSize endp

;создание PropertySheet
Properties proc uses ebx
;заполняем структуры
xor eax, eax
mov edx, [hWnd]
mov ebx, [hInstance]
lea ecx, PSPages
mov [PSHeader.dwSize], size PROPSHEETHEADERA
mov [PSHeader.dwFlags], PSH_NOAPPLYNOW+PSH_PROPSHEETPAGE+PSH_USEHICON
mov [PSHeader.hwndParent], edx
mov [PSHeader.hInstance], ebx
m2m [PSHeader.hIcon], [hIcon] ;пиктограмма
mov [PSHeader.pszCaption], offset szHeader ;заголовок
mov [PSHeader.nPages], 2 ;2 страницы
mov [PSHeader.nStartPage], eax ;стартовая - первая
mov [PSHeader.ppsp], ecx
mov [PSHeader.pfnCallback], eax
mov [PSHeader.hbmWatermark], eax
mov [P SHeader.hplWatermark], eax
mov [PSHeader.hbmHeader], eax

mov [(PROPSHEETPAGE ptr [ecx]).dwSize], size PROPSHEETPAGE
mov [(PROPSHEETPAGE ptr [ecx]).dwFlags], PSP_DEFAULT + PSP_HIDEHEADER
mov [(PROPSHEETPAGE ptr [ecx]).hInstance], ebx
mov [(PROPSHEETPAGE ptr [ecx]).pResource], IDD_DLG1 ;имя диалога в ресурсах
mov [(PROPSHEETPAGE ptr [ecx]).hIcon], eax
mov [(PROPSHEETPAGE ptr [ecx]).pszTitle], eax
mov [(PROPSHEETPAGE ptr [ecx]).pfnDlgProc], PSDialog1;функция окна
mov [(PROPSHEETPAGE ptr [ecx]).lParam], eax
mov [(PROPSHEETPAGE ptr [ecx]).pfnCallback], eax
mov [(PROPSHEETPAGE ptr [ecx]).pcRefParent], eax

add ecx, size PROPSHEETPAGE
mov [(PROPSHEETPAGE ptr [ecx]).dwSize], size PROPSHEETPAGE
mov [(PROPSHEETPAGE ptr [ecx]).dwFlags], PSP_DEFAULT + PSP_HIDEHEADER
mov [(PROPSHEETPAGE ptr [ecx]).hInstance], ebx
mov [(PROPSHEETPAGE ptr [ecx]).pResource], IDD_DLG2 ;имя диалога в ресурсах
mov [(PROPSHEETPAGE ptr [e cx]).hIcon], eax
mov [(PROPSHEETPAGE ptr [ecx]).pszTitle], eax
mov [(PROPSHEETPAGE ptr [ecx]).pfnDlgProc], PSDialog2;функция окна
mov [(PROPSHEETPAGE ptr [ecx]).lParam], eax
mov [(PROPSHEETPAGE ptr [ecx]).pfnCallback], eax
mov [(PROPSHEETPAGE ptr [ecx]).pcRefParent], eax

invoke PropertySheet, addr PSHeader ;создаем и "сидим" в нем, пока не выйдем

ret
Properties endp

;вводим имя файла
;универсальная, как для вызова как GetOpenFileName, так и GetSaveFileName
GetFileName proc uses edi, pFName:dword, \ ;имя текущего файла
pFilter:dword,\ ;фильтр
fun:dword, \ ;функция, которая вызывается
pTitle:dword ;заголовок диалога
LOCAL ofn:OPENFILENAMEA

STRING szCurrPath,"." ;начальный путь - текущая папка

lea edi, ofn
mov ecx, (size OPENFILENAMEA) / 4
xor eax, eax
rep stosd
lea eax, [ofn]
mov [(OPENFILENAMEA ptr [eax]).lStructSize], size OPENFILE NAMEA
m2m [(OPENFILENAMEA ptr [eax]).lpstrFile], pFName ;имя текущего файла
mov [(OPENFILENAMEA ptr [eax]).nMaxFile], 256 ;его м акс длина
m2m [(OPENFILENAMEA ptr [eax]).lpstrFilter], pFilter ;фильтр
m2m [(OPENFILENAMEA ptr [eax]).lpstrTitle], pTitle ;заголовок диалога
mov [(OPENFILENAMEA ptr [eax]).lpstrInitialDir], offset szCurrPath ;текущий путь
mov [(OPENFILENAMEA ptr [eax]).Flags], OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY

push eax ;параметр - адрес структуры
mov eax, [fun] ;адрес функции
call dword ptr eax ;вызываем
ret
GetFileName endp

;сохранение файла
SaveFile proc uses edi esi ebx, hwnd:DWORD
local dwHiLen:dword ;для старшего dword-а длины
;запросим имя TXT-файла
;проверим, было ли введено имя файла
.if [szNameTXT] == 0 ;первый байт == 0?
lea edi, [szDefault] ;если да, то берем имя файла по-умолчанию
.else
lea edi, [szNameTXT]
.endif
;ждем имя файла для записи
invoke GetFileName,edi,offset szFilterTXT,GetSaveFileName,offset szTitleSave
;что-то ввели?
.if eax != 0
pu sh edi ;сохраним имя файла
;получим описатель Edit-а на странице диалога
mov edi, rv(GetDlgItem, [hwnd], IDC_TEXT) ;edi - описатель окна редактора
mov ebx, rv(GetWindowTextLength, edi) ;ebx - длина содержимого
inc ebx ;учтем завершающий 0
mov esi, rv(GlobalAlloc, GMEM_FIXED, ebx) ;esi - адрес памяти под данные

invoke GetWindowText, edi, esi, ebx ;получим данные
pop edi ;edi - имя файла
;создаем файл на запись со сбросом в 0, если он уже был
mov edi, rv(CreateFile,edi,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0)
;в edi - описатель открытого файла
dec ebx ;последний 0 не пишем
;пишем файл
invoke WriteFile, edi, esi, ebx, ADDR dwHiLen, 0

invoke CloseHandle, edi ;закрываем файл
invoke GlobalFree, esi ;освобождаем память
mov fChange, 0 ;сбросим флаг изменения
.endif
ret
SaveFile endp

;новая функция окна для редактора
KeyProcEdit proc hwnd:dword, message:dword, wParam:dword, lParam:dword
;отрабатываем только правую кнопку мыши
.if message == WM_RBUTTONDOWN
;чуть-чуть подправим позицию курсора, чтобы совпало с тем, что вне редактора (экспериментально)
add [lParam], 140010h
;получим родителя редактора
invoke GetParent, [hwnd]
;перенаправим ему сообщение
invoke SendMessage, eax, message, wParam, lParam
xor eax, eax
.else
;все остальное не трогаем
invoke CallWindowProc, pKeyDefProcEdit, [hwnd],[message], [wParam], [lParam]
.endif
ret
KeyProcEdit endp

end start
Файл ресурсов rsrc.rc
Код:
#include "\masm32\include\resource.h"

#define IDI_ICON 500
#define IDD_DLG1 101
#define IDD_DLG2 102
#define IDC_TEXT 301
#define IDC_FILENAME 302
#define IDC_STATIC -1

IDI_ICON ICON MOVEABLE PURE LOADONCALL DISCARDABLE "property.ico"

IDD_DLG1 DIALOG 0, 0, 300, 246
STYLE WS_POPUP | WS_CAPTION
CAPTION "Text"
FONT 8, "MS Sans Serif"
BEGIN
GROUPBOX "", IDC_FILENAME, 6, 4, 288, 234
EDITTEXT IDC_TEXT,10,12,280,222,WS_VSCROLL | WS_HSCROLL | ES_AUTOHSCROLL |
ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | NOT WS_BORDER, WS_EX_STATICEDGE
END


IDD_DLG2 DIALOG 0, 00, 300, 246
STYLE WS_POPUP | WS_CAPTION
CAPTION "BitMap"
FONT 8, "MS Sans Serif"
BEGIN
GROUPBOX "", IDC_FILENAME, 6, 4, 288, 234
END
Прикрепленный файл: загрузить »

-----
Удачи!

Ответ отправил: Лысков Игорь Витальевич, Модератор
Ответ отправлен: 31.03.2010, 16:25
Номер ответа: 260497
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru
Абонент Skype: igorlyskov

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 260497 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.14 от 03.03.2010

    В избранное