以下是引用csyx在2022-3-17 22:51:31的发言:
图片缩小点,以免喧宾夺主
图片缩小点,以免喧宾夺主

选取文件夹对话框 与 选取文件名对话框 的样子一样不是不可以,就是有点难为VFP。
通过 GetOpenFileName 的 OPENFILENAME 结构体成员 lpfnHook,在 lpfnHook 的回调函数拦截处理相关消息就可以。
“回调函数”使用的是“函数指针”,VFP没有提供这类型的函数。
VFP不是不可以做,只是真没必要,有这精力不如花点点时间学点C就轻松搞定。
** ** StructCalss_DirDialog.prg ** #INCLUDE StructCalss.h SET PROCEDURE TO StructCalss.prg ADDITIVE LoadApi() ? myGetDir("c:\temp\test") SET PROCEDURE TO CLEAR ALL RETURN FUNCTION myGetDir(cDefDir) LOCAL bi, fa, pDir, pDefDir, cDir, pci, pit pDir = apiMalloc(MAX_PATH) pDefDir = myStrptr(cDefDir) fa = CREATEOBJECT("FUNCTIONADDRESS") bi = CREATEOBJECT("BROWSEINFOA") bi.setValue("pszDisplayName", pDir) bi.setValue("lpfn", fa.GetFunAddr("CallbackProc",4)) bi.setValue("lParam", pDefDir) pit = apiSHBrowseForFolder(bi.pBuffer) cDir = "" IF pit > 0 apiSHGetPathFromIDList(pit, pDir) cDir = SYS(2600, pDir, apiStrlen(pDir)) apiCoTaskMemFree(pit) ENDIF apiFree(pDefDir) apiFree(pDir) RETURN cDir ENDFUNC ** 回调函数 FUNCTION CallbackProc(hWnd, Msg, wParam, lParam) IF Msg == BFFM_INITIALIZED * BFFM_SETSELECTIONA 消息自动选择初始路径 apiSendMessage(hWnd, BFFM_SETSELECTIONA, BFFM_INITIALIZED, lParam) ENDIF RETURN 0 ENDFUNC * 获取调用VFP函数的函数指针 DEFINE CLASS FUNCTIONADDRESS as Session DIMENSION aPFunction[1] hUser32 = 0 fMessageBox = 0 pMsg = 0 pTitle = 0 hMSvcrt = 0 fSwprintf = 0 hOleaut32 = 0 fSysAllocString = 0 fSysFreeString = 0 pFunName = 0 PROCEDURE Init this.hUser32 = apiLoadLibrary("user32.dll") this.fMessageBox = apiGetProcAddress(this.hUser32, "MessageBoxA") this.pMsg = myStrptr("调用 FUNCTIONADDRESS 类 GetFunAddr() 失败") this.pTitle = myStrptr("提示") this.hMSvcrt = apiLoadLibrary("msvcrt.dll") this.fSwprintf = apiGetProcAddress(this.hMSvcrt, "swprintf") this.hOleaut32 = apiLoadLibrary("oleaut32.dll") this.fSysAllocString = apiGetProcAddress(this.hOleaut32, "SysAllocString") this.fSysFreeString = apiGetProcAddress(this.hOleaut32, "SysFreeString") ENDPROC PROCEDURE Destroy LOCAL pf FOR EACH pf IN this.aPFunction apiFree(pf) ENDFOR apiFree(this.pMsg) apiFree(this.pTitle) apiFree(this.pFunName) apiFreeLibrary(this.hUser32) apiFreeLibrary(this.hMSvcrt) apiFreeLibrary(this.hOleaut32) ENDPROC FUNCTION GetFunAddr(cFunName, nParameters) && 函数名,参数个数 LOCAL nCount, cCode, cMsgCode IF EMPTY(cFunName) RETURN 0 ENDIF * 格式:函数名(%d,%d,......%d,%d) cFunName = STRCONV(cFunName + "(%d" + REPLICATE(",%d", nParameters - 1) + ")"+0h00, 5) this.pFunName = myStrptr(cFunName) * 出错提示 cMsgCode = "" cMsgCode = cMsgCode + 0h6A00 && push 0 MessageBox()第4个参数 cMsgCode = cMsgCode + 0h68 + BINTOC(this.pTitle,"4RS") && push pTitle MessageBox()第3个参数 cMsgCode = cMsgCode + 0h68 + BINTOC(this.pMsg, "4RS") && push pMsg MessageBox()第2个参数 cMsgCode = cMsgCode + 0h6A00 && push 0 MessageBox()第1个参数 cMsgCode = cMsgCode + 0hB8 + BINTOC(this.fMessageBox,"4RS") && move eax, fMessageBox cMsgCode = cMsgCode + 0hFFD0 && call MessageBox cMsgCode = cMsgCode + 0hB801000000 && mov eax,00000001h 返回1(.T.) * * 函数的二进制代码 * * 保存栈顶指针 ebp <- esp, 调整栈顶指针esp <- (esp-2000)预留足够栈空间 cCode = 0h55 && PUSH EBP 保存ebp cCode = cCode + 0h8BEC && MOV EBP,ESP 栈顶指针保存到ebp作为栈基址 cCode = cCode + 0h81EC + BINTOC(2000, "4RS") && SUB ESP,000007D0h 预留2000字节足够栈空间 * swprintf(pOut, "<VFP函数名>(%d,%d,...,%d,%d)", ect1, ect2,..., ectn-1, ectn) * 调用swprintf(pOut, pFmt, ect),将输出参数 pOut 的内容作为VFP函数表达式 * pOut,输出,指向VFP函数表达式的指针, 表达式: "<VFP函数名>(<数值1>,<数值2>,...,<数值n>)" * pFmt,输入,指向VFP函数格式字符串的指针, 表达式: "<VFP函数名>(%d,%d,...,%d)" * ect, 输入,参数表,<数值1>,<数值2>,...,<数值n> * * 函数的输入参数作为swprintf()的ect参数,输出转换为VFP函数的输入参数 * 参数入栈代码 FOR i = nParameters TO 1 STEP -1 cCode = cCode; + 0h8B45 + CHR(4 + i * 4); + 0h50 ENDFOR * ectn * ...... ectn-1 * * 0h8B450C && MOV EAX, DWORD PTR [EBP+0C] ect2 * 0h50 && PUSH EAX * 0h8B4508 && MOV EAX, DWORD PTR [EBP+08] ect1 * 0h50 && PUSH EAX cCode = cCode + 0hB8 + BINTOC(this.pFunName, "4RS") && MOV EAX, pVFP函数 pFmt cCode = cCode + 0h50 && PUSH EAX cCode = cCode + 0h8D45A0 && LEA EAX, [EBP-60h] pOut cCode = cCode + 0h50 && PUSH EAX cCode = cCode + 0hB8 + BINTOC(this.fSwprintf, "4RS") && MOV EAX, fSwprintf cCode = cCode + 0hFFD0 && CALL EAX 调用swprintf() * 因 swfprintf() 不会自动恢复堆栈指针 * esp 恢复到调用swfprintf()前状态,esp <- esp + (n参数个数+2)*4) cCode = cCode + 0h83C4 + CHR((nParameters + 2) * 4) && ADD ESP,(n参数个数+2)*4) * [EBP-10h] = SysAllocString([EBP-60h]) * 调用SysAllocString()将VFP函数表达式字符串转换成BSTR字符串 cCode = cCode + 0h8D45A0 && LEA EAX,[EBP-60h] 指向VFP函数表达式字符串指针 cCode = cCode + 0h50 && PUSH EAX 作为SysAllocString()输入参数 cCode = cCode + 0hB8 + BINTOC(this.fSysAllocString, "4RS") && MOV EAX, fSysAllocString cCode = cCode + 0hFFD0 && CALL EAX 调用SysAllocString() * 保存SysAllocString()返回的BSTR字符串指针,之后由SysFreeString()释放 cCode = cCode + 0h8945F0 && MOV [EBP-10h],EAX * _VFP.DoCmd(<VFP函数表达式>) * 转换成BSTR字符串的VFP函数表达式, 作为调用_VFP对象DoCmd方法的输入参数 cCode = cCode + 0h50 && PUSH EAX cCode = cCode + 0hB8 + BINTOC(SYS(3095, _VFP), "4RS") && MOV EAX, SYS(3095, _VFP) 获取_VFP对象的IDispatch指针 cCode = cCode + 0h50 && PUSH EAX _VFP指针 cCode = cCode + 0h8B00 && MOV EAX,[EAX] 获取_VFP的函数表指针 cCode = cCode + 0h0584000000 && ADD EAX,00000084h _函数表指针偏移 84h 是_VFP.DoCmd函数的指针 cCode = cCode + 0hFF10 && CALL [EAX] 调用_VFP.DoCmd(<VFP函数表达式>) **cCode = cCode + 0hB800000000 && MOV EAX,00000000h eax <- 0 (DoCmd()返回NULL) * 是否成功返回0 cCode = cCode + 0h83F800 && CMP EAX, 0 * 是,成功返回,跳过出错提示。 cCode = cCode + 0h74 + CHR(LEN(cMsgCode)) && je len(cMsgCode), je=0h74(等于), jne=0h75(不等于) cCode = cCode + cMsgCode && 出错提示代码 * SysFreeString([EBP-10h]) * 释放由SysAllocString()分配生成BSTR字符串的空间 cCode = cCode + 0h8B45F0 && MOV EAX,[EBP-10h] cCode = cCode + 0h50 && PUSH EAX cCode = cCode + 0hB8 + BINTOC(this.fSysFreeString, "4RS") && MOV EAX, fSysFreeString cCode = cCode + 0hFFD0 && CALL EAX 调用SysFreeString() cCode = cCode + 0hB801000000 && MOV EAX,00000001h 返回1(.T.) **cCode = cCode + 0hB800000000 && MOV EAX,00000000h 返回0(.F.) cCode = cCode + 0h8BE5 && MOV ESP,EBP 恢复栈顶指针 cCode = cCode + 0h5D && POP EBP 恢复ebp * 返回,按“堆栈平衡”原则,被调用者把堆栈指针修正到调用前的状态。 * RET n参数个数*4,即 esp <- (esp + n参数个数*4),因调用者首先把参数压入堆栈 cCode = cCode + 0hC2 + BINTOC(nParameters * 4, "4RS") && RET n参数个数*4 nCount = ALEN(this.aPFunction) + IIF(!EMPTY(this.aPFunction[1]), 1, 0) DIMENSION this.aPFunction[nCount] && 函数指针数组 this.aPFunction[nCount] = apiMalloc(LEN(cCode)) && 分配函数代码内存空间 SYS(2600, this.aPFunction[nCount], LEN(cCode), cCode) && 载入函数代码 RETURN this.aPFunction[nCount] && 返回函数指针 ENDFUNC ENDDEFINE
[此贴子已经被作者于2022-3-20 14:57编辑过]
[此贴子已经被作者于2022-3-19 16:46编辑过]