初探从C到Win32汇编之系列二

来源:互联网 发布:mac网络测速软件 编辑:程序博客网 时间:2024/06/09 17:07

世味年来薄似纱,谁令骑马客京华?
小楼一夜听春雨,深巷明朝卖杏花。
矮纸斜行闲作草,晴窗细乳戏分茶。
素衣莫起风尘叹,犹及清明可到家。

缘起《圆月弯刀》之“小楼一夜听春雨”,才感此作之魅。

芳草惜惜,幽谷秀。花香怡怡,缤彩蝶。  
轻抚玄琴奏妙曲,小楼听雨舞弯刀,皆往矣!  
爱也罢,恨也罢,寻寻觅觅。此情可待,却已成追忆!  
流星逝去,而今,只剩孤魂飘零明月间。

于是来了兴致,才有此文。

细说打开文件对话框 OPENFILENAME结构的OFN_ALLOWMULTISELECT 位标记(指定文件名列表框允许多选)。
对于这个属性相信许多人很纠结,主要是在单选与多选时是不同的。
看看数据区就知道了:


                                           图1 单选文件 


                                           图2 多选文件
发现单选文件时,得到的是形如
"C:/Documents and Settings/Administrator/桌面/myOK/小楼一夜听春雨,深巷明朝卖杏花。.txt "的全路径。
而多选文件时,得到的是形如
"C:/Documents and Settings/Administrator/桌面/myOK”  “ 小楼一夜听春雨,深巷明朝卖杏花。.txt "
"世味年来薄似纱,谁令骑马客京华?.asm"

为什么要分析这个东西呢,主要有以下几点:
1.为文件的选择提供一个统一处理接口
2.实现文件扩展名的提取与识别
3.为文件列表(比如播放文件列表)的形成提供一点思路。

程序花了一上午才写好,丢人了嘿嘿。c程序就不晒了,只写了个Win32汇编的,慢慢看。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;1.为文件的选择提供一个统一处理接口
;2.实现文件扩展名的提取与识别
;3.为文件列表(比如播放文件列表)的形成提供一点思路。
;By GoldenSpider 2010-6-21 QQ:287014897
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
        .386
        .model flat, stdcall
        option casemap :none   ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;    Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
includelib    kernel32.lib
includelib    user32.lib
includelib    gdi32.lib
includelib    comctl32.lib
includelib    comdlg32.lib

include       windows.inc
include       kernel32.inc
include       user32.inc
include       gdi32.inc
include       comctl32.inc
include       comdlg32.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;    Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN      equ        1000
ID_BROWSE    equ        1001
ID_FILE           equ        1002
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;    数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
        .data?
hWinMain    dd    ?
hInstance    dd    ?
lpBuffer       dd    ?
szBuffer      db    MAX_PATH*40    dup    (?)    ;多个文件名使用的缓冲区
szTemp       db    MAX_PATH    dup    (?)    ;保存文件名路径前缀
szTemp1     db    MAX_PATH    dup (?)
szTemp2     db    MAX_PATH    dup (?)
szPath         db    MAX_PATH    dup    (?)
;buf             db 256 dup(?)
stOpenFileName    OPENFILENAME    <?>
        .data
inform             db    0dh,0ah,0
szTitleSave    db    "    叶听雨 By G-Spider",0
szTitleMesg db  "    临安春雨初霁  陆游",0
szExt        db    '*.txt;*.c',0
szFilter    db    'Files(*.txt,*.c)',0,'*.txt;*.c',0,'ALL Files(*.*)',0,'*.*',0,0
;buffmt db "%d",0   ;///用于数值数据测试
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;    子程序声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain    PROTO    :DWORD,:DWORD,:DWORD,:DWORD
_GetFileName    PROTO
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;    代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;*******************************************************************
;文件处理,Good job! By GoldenSpider
;功能:  不论单选多选,均将由得到的lpstrFile全路径
;           分割为A="***/" B="***" "***"..."***" 其中A为全路径前缀,B为各文件名(包含扩展名)
;返回值:B的头指针(不包括全路径前缀A,前缀A存入szTemp缓存中)
;举例1:单选得到"D:/masm32/my.asm"分割为:A="D:/masm32/" B="my.asm"
;举例2:多选得到"D:/masm32" "my.asm" "my1.c"处理为:A="D:/masm32/" B="my.asm" "my1.c"
;           以上两例返回值均为"my.asm"的头指针 ,串"D:/masm32/"在szTemp缓存中

;*******************************************************************
_GetFileName    proc
        
    mov    stOpenFileName.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
    mov    stOpenFileName.lStructSize,SIZEOF stOpenFileName
    mov    eax,hWinMain
    mov    stOpenFileName.hWndOwner,eax
    mov    stOpenFileName.lpstrFilter,offset szFilter
    mov    stOpenFileName.lpstrFile,offset szBuffer
    mov    stOpenFileName.nMaxFile,MAX_PATH
    mov    stOpenFileName.lpstrInitialDir,0
    mov    stOpenFileName.lpstrTitle,offset szTitleMesg
    mov    stOpenFileName.lpstrDefExt,offset szExt
    mov    stOpenFileName.Flags,OFN_HIDEREADONLY or OFN_FILEMUSTEXIST /
            or OFN_PATHMUSTEXIST or OFN_EXPLORER or OFN_ALLOWMULTISELECT
    invoke    GetOpenFileName,offset stOpenFileName
        
    .if    eax == FALSE    
            ret
    .endif
        invoke    SetDlgItemText,hWinMain,ID_FILE,addr szBuffer
    xor ebx,ebx
    mov    bx,stOpenFileName.nFileOffset
    invoke    lstrcpyn,offset szTemp,offset szBuffer, ebx ;///得到A串    
  ;以下处理尾符'/'
    invoke    lstrlen,offset szTemp
    lea esi,szTemp
    add    esi,eax
    xor    eax,eax
    mov    al,'/'
    .if    BYTE PTR [esi-1]!=al    
           mov    WORD ptr [esi],ax
    .endif        
                
    xor     ebx,ebx
    mov    bx,stOpenFileName.nFileOffset
    lea       esi,szBuffer
    add      esi,ebx    
    mov     eax,esi

    ret
_GetFileName    endp
;********************************************************************
;PathFindExtensionA    By G-Spider[月窟]
;PathFindExtension功能:返回形如路径“D:/masm32/examples/lcd.asm"串的后缀串".asm"的头指针
;输入参数:路径指针lpPathBuffer,可以由lpstrFile得到
;返回值:eax

;********************************************************************
PathFindExtension    Proc uses ESI lpPathBuffer:DWORD
;----------------------------------------------------------------------
         mov eax,lpPathBuffer
         XOR ESI,ESI            
         TEST EAX,EAX            
         JE SHORT L77F5F625        
         MOV CL,BYTE PTR DS:[EAX]    
         TEST CL,CL            
         JE SHORT L77F5F625        
L77F5F603 :      
         CMP CL,20h            ;20H=32D,为ASCII代码SPACE,即查看是不是空格字符
         JE SHORT L77F5F62A        ;如果是SPACE,则跳转
         CMP CL,2Eh            ;2EH=46D,为ASCII代码 '.',即查看是否为点号
         JE SHORT L77F5F5E5        ;如果是点号,则跳转
         CMP CL,5Ch            ;5CH=92D,为ASCII代码'/',即查看是否为分隔斜杠
         JE SHORT L77F5F62A        ;如果是斜杠,则跳转
L77F5F612 :        

          PUSH EAX                                                
          CALL CharNextA

           MOV CL,BYTE PTR DS:[EAX]    
          TEST CL,CL            
          JNZ SHORT L77F5F603        
           TEST ESI,ESI                    
           JE SHORT L77F5F625
           MOV EAX,ESI            
L77F5F625 :        
        ret
L77F5F62A :      
    XOR ESI,ESI            ;说明'.'点号后面的不是后缀形式,于是将该指针清0,不用再保存这个点的指针值
    JMP SHORT L77F5F612
                    
L77F5F5E5 :      
    MOV ESI,EAX            ;若为'.'点符,则用ESI保存其指针值
    JMP SHORT L77F5F612        ;接着判断下一位字符                    
;----------------------------------------------------------------------
PathFindExtension    EndP
;********************************************************************
_ProcDlgMain    proc    uses ebx edi esi, /
        hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
        Local @StrLongCount;///用于保存带后缀的文件名串长
        Local @DelExtCount ;///用于保存剔除了后缀的文件名串长
        
        mov @StrLongCount,0
        mov @DelExtCount,0
        
        mov    eax,wMsg
        .if    eax == WM_CLOSE
            invoke    EndDialog,hWnd,NULL
        .elseif    eax == WM_INITDIALOG
            mov    eax,hWnd
            mov    hWinMain,eax
            invoke    SendDlgItemMessage,hWinMain,ID_FILE,EM_SETREADONLY,TRUE,NULL
        .elseif    eax == WM_COMMAND
            mov    eax,wParam
            .if    eax == ID_BROWSE
                invoke    _GetFileName                
                mov    lpBuffer,eax ;得到文件名指针
                ;///invoke    lstrcat,addr szTemp,lpBuffer    ;显示全路径
            .elseif eax == IDOK    
                invoke    lstrlen,lpBuffer
                mov @StrLongCount,eax
                mov    @DelExtCount,eax
                .repeat
                    invoke     PathFindExtension,lpBuffer
                    invoke    lstrlen,eax
                    dec eax
                    sub    @DelExtCount,eax
                    ;invoke wsprintf,offset buf,offset buffmt,ExtCount   ;///用于测试
                    ;invoke MessageBox,NULL,offset buf,addr szTitleSave,0

                    invoke    lstrcpyn,offset szTemp1,lpBuffer,@DelExtCount ;剔除形如.asm的文件名后缀
                    invoke    lstrcat,addr szTemp1,addr inform     ;加上回车换行符
                    invoke    lstrcat,addr szTemp2,addr szTemp1     ;形成连续的长串

                    mov eax,@StrLongCount
                    inc eax
                    add lpBuffer,eax  ;指向下个子串的头部
                    invoke    lstrlen,lpBuffer
                    mov    @StrLongCount,eax
                    mov    @DelExtCount,eax
                    
                .until eax==0
                invoke MessageBox,hWinMain,addr szTemp2,addr szTitleMesg,0 ;显示诗句          
           .endif
        .else
;********************************************************************
;    注意:对话框的消息处理后,要返回 TRUE,对没有处理的消息
;    要返回 FALSE
;********************************************************************
            mov    eax,FALSE
            ret
        .endif          
        mov    eax,TRUE
        ret      
_ProcDlgMain    endp
;********************************************************************
start:
        invoke    InitCommonControls
        invoke    GetModuleHandle,NULL
        mov    hInstance,eax
        invoke    DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0
        invoke    ExitProcess,NULL

        end    start
;********************************************************************



原创粉丝点击