| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1606 人关注过本帖
标题:请教:调用Windows API时,如何正确地传递struct(结构体)参数?
只看楼主 加入收藏
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:347
专家分:326
注 册:2013-10-4
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:6 
请教:调用Windows API时,如何正确地传递struct(结构体)参数?
(先发句牢骚:我好像还从未在VFP代码中成功传递过struct参数!)

我们知道,VFP的Editbox控件十分简陋,在Windows 7/10/11中显示文字密密麻麻的,用户体验很难受。而RichTextBox控件相对好一些,在文字排版方面添加了许多选项,不过若想要调整行距,也得历经千辛万苦!因为没有现成的“行距”属性,必须借助SendMessage()调用API才能够更改。

百度一下:“调整RichEdit行间距”,于是找到这样一段C代码:

//======================
void __fastcall TForm1::Button1Click(TObject *Sender)
{undefined
  PARAFORMAT2 pf;
  pf.cbSize=sizeof(PARAFORMAT2); //识别paraformat与paraformat2
  pf.dwMask=PFM_LINESPACING;
  pf.dyLineSpacing=300; //行距在此设置
  pf.bLineSpacingRule=4;

  SendMessage(RzRichEdit1->Handle,EM_SETPARAFORMAT,0,LPARAM(&pf));
...
//======================

赶紧查资料!我们可以“翻译”出调用这个API所需的VFP代码是:

SendMessage(Handle, EM_SETPARAFORMAT, 0, @pf)

其中涉及的参数是:
#define WM_USER 0x0400
#define EM_SETPARAFORMAT (WM_USER + 71)
sizeof(PARAFORMAT) = 156
sizeof(PARAFORMAT2) = 188

typedef struct _paraformat {
  UINT  cbSize;
  DWORD dwMask;
  WORD  wNumbering;
  union {
    WORD wReserved;
    WORD wEffects;
  };
  LONG  dxStartIndent;
  LONG  dxRightIndent;
  LONG  dxOffset;
  WORD  wAlignment;
  SHORT cTabCount;
  LONG  rgxTabs[MAX_TAB_STOPS];
} PARAFORMAT;

struct PARAFORMAT2 : _paraformat {
  LONG  dySpaceBefore;
  LONG  dySpaceAfter;
  LONG  dyLineSpacing;
  SHORT sStyle;
  BYTE  bLineSpacingRule;
  BYTE  bOutlineLevel;
  WORD  wShadingWeight;
  WORD  wShadingStyle;
  WORD  wNumberingStart;
  WORD  wNumberingStyle;
  WORD  wNumberingTab;
  WORD  wBorderSpace;
  WORD  wBorderWidth;
  WORD  wBorders;
};

需传递的struct PARAFORMAT2,只用到了其中这4个字段:
cbSize = 0x000000BC(4字节:其值为结构体总长度 = 十进制188)
dwMask = 0x00000100(4字节:其值为修改行距所对应的Mask = 十进制256)
dyLineSpacing = 0x0000012C(4字节:其值为自己设置的行距值 = 十进制300,单位为twips)
bLineSpacingRule = 0x04(1字节:其值意思是确定改行距的单位为twips)

关键是如何创建一个188字节的字符串,来模拟这个PARAFORMAT2结构体。
我试了半天,一直无法成功,鼓捣成下边这个样子,却一直被VFP报错:
*----------------------
*设置行距
#define WM_USER 0x0400
#define EM_SETPARAFORMAT (WM_USER + 71)
pf = 0hBC000000 + 0h00010000 + REPLICATE(CHR(0), 156) + 0h2C010000 + 0h0000 + CHR(4) + REPLICATE(CHR(0), 17)
SendMessage(this.Hwnd, EM_SETPARAFORMAT, 0, @pf)
*----------------------
C语言的“大端、小端”已搞得我头晕脑胀、一头雾水……
急急求助:怎么破?
搜索更多相关主题的帖子: struct WORD 调用 LONG 行距 
2022-03-13 20:42
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10559
专家分:42996
注 册:2014-5-20
收藏
得分:0 
PARAFORMAT2
MSASM定义
程序代码:
PARAFORMAT2 STRUCT
  cbSize            DWORD    ?
  dwMask            DWORD    ?
  wNumbering        WORD     ?
  wEffects          WORD     ?
  dxStartIndent     DWORD    ?
  dxRightIndent     DWORD    ?
  dxOffset          DWORD    ?
  wAlignment        WORD     ?
  cTabCount         WORD     ?
  rgxTabs           DWORD MAX_TAB_STOPS dup(?)
  dySpaceBefore     DWORD    ?
  dySpaceAfter      DWORD    ?
  dyLineSpacing     DWORD    ?
  sStyle            WORD     ?
  bLineSpacingRule  BYTE     ?
  bOutlineLevel     BYTE     ?
  wShadingWeight    WORD     ?
  wShadingStyle     WORD     ?
  wNumberingStart   WORD     ?
  wNumberingStyle   WORD     ?
  wNumberingTab     WORD     ?
  wBorderSpace      WORD     ?
  wBorderWidth      WORD     ?
  wBorders          WORD     ?
PARAFORMAT2 ENDS

CPP定义
程序代码:
typedef struct _paraformat2
{
    UINT    cbSize;
    DWORD    dwMask;
    WORD    wNumbering;
    WORD    wReserved;
    LONG    dxStartIndent;
    LONG    dxRightIndent;
    LONG    dxOffset;
    WORD    wAlignment;
    SHORT    cTabCount;
    LONG    rgxTabs[MAX_TAB_STOPS];
     LONG    dySpaceBefore;            /* Vertical spacing before para            */
    LONG    dySpaceAfter;            /* Vertical spacing after para            */
    LONG    dyLineSpacing;            /* Line spacing depending on Rule        */
    SHORT    sStyle;                    /* Style handle                            */
    BYTE    bLineSpacingRule;        /* Rule for line spacing (see tom.doc)    */
    BYTE    bOutlineLevel;            /* Outline Level                        */
    WORD    wShadingWeight;            /* Shading in hundredths of a per cent    */
    WORD    wShadingStyle;            /* Byte 0: style, nib 2: cfpat, 3: cbpat*/
    WORD    wNumberingStart;        /* Starting value for numbering            */    
    WORD    wNumberingStyle;        /* Alignment, Roman/Arabic, (), ), ., etc.*/
    WORD    wNumberingTab;            /* Space bet 1st indent and 1st-line text*/
    WORD    wBorderSpace;            /* Border-text spaces (nbl/bdr in pts)    */
    WORD    wBorderWidth;            /* Pen widths (nbl/bdr in half twips)    */
    WORD    wBorders;                /* Border styles (nibble/border)        */
} PARAFORMAT2;

2022-03-13 22:10
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10559
专家分:42996
注 册:2014-5-20
收藏
得分:0 
MAX_TAB_STOPS = 32
可以用BINTOC()转换,BINTOC(num,"xRS") x:1(BYTE)或2(WORD)或4(DWORD)
2022-03-13 22:16
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:347
专家分:326
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2022-3-13 22:10:50的发言:
PARAFORMAT2
CPP定义
typedef struct _paraformat2
{
    UINT    cbSize;
    DWORD    dwMask;
    WORD    wNumbering;
    WORD    wReserved;
    LONG    dxStartIndent;
    LONG    dxRightIndent;
    LONG    dxOffset;
    WORD    wAlignment;
    SHORT    cTabCount;
    LONG    rgxTabs[MAX_TAB_STOPS];
     LONG    dySpaceBefore;            /* Vertical spacing before para            */
    LONG    dySpaceAfter;            /* Vertical spacing after para            */
    LONG    dyLineSpacing;            /* Line spacing depending on Rule        */
    SHORT    sStyle;                    /* Style handle                            */
    BYTE    bLineSpacingRule;        /* Rule for line spacing (see tom.doc)    */
    BYTE    bOutlineLevel;            /* Outline Level                        */
    WORD    wShadingWeight;            /* Shading in hundredths of a per cent    */
    WORD    wShadingStyle;            /* Byte 0: style, nib 2: cfpat, 3: cbpat*/
    WORD    wNumberingStart;        /* Starting value for numbering            */   
    WORD    wNumberingStyle;        /* Alignment, Roman/Arabic, (), ), ., etc.*/
    WORD    wNumberingTab;            /* Space bet 1st indent and 1st-line text*/
    WORD    wBorderSpace;            /* Border-text spaces (nbl/bdr in pts)    */
    WORD    wBorderWidth;            /* Pen widths (nbl/bdr in half twips)    */
    WORD    wBorders;                /* Border styles (nibble/border)        */
} PARAFORMAT2;


感谢吹版热心指教!
若改用VC去SendMessage则无问题,若企图用VFP字符串伪装成struct,则永远报错“(PARAFORMAT2)数据类型不匹配”。
之前真有些想当然啦,呵呵,VFP这一块应用我真不太熟。


[此贴子已经被作者于2022-3-14 00:06编辑过]

2022-03-13 23:15
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10559
专家分:42996
注 册:2014-5-20
收藏
得分:20 
以下是引用cssnet在2022-3-13 23:15:43的发言:



感谢吹版热心指教!
若改用VC去SendMessage则无问题,若企图用VFP字符串伪装成struct,则永远报错“(PARAFORMAT2)数据类型不匹配”。
之前真有些想当然啦,呵呵,VFP这一块应用我真不太熟。

“数据类型不匹配”是API参数声明不对,还是结构成员没对准位置。
调用API涉及到结构类型,VFP通常用字符串来表达,易读性差,不好理解,容易搞错。可以将结构封装成一个类,用结构成员名称来表达操作。
图片附件: 游客没有浏览图片的权限,请 登录注册

DECLARE long SendMessage IN user32 long,long,long,string@
#define WM_USER 0x0400
#define EM_SETPARAFORMAT (WM_USER + 71)
pf = BINTOC(188,"4RS") + BINTOC(256,"4RS") + REPLICATE(0h00,156);
   + BINTOC(500,"4RS") + 0h0000 + BINTOC(4,"1RS") + REPLICATE(0h00,17)
SendMessage(thisform.rich1.Hwnd, EM_SETPARAFORMAT, 0, @pf)
thisform.rich1.seltext = "123456789"+0h0D0A+"abcdefghijk"+0h0D0A+"ABCDEFGHIJK"++0h0D0A



收到的鲜花
  • 厨师王德榜2022-03-14 15:57 送鲜花  1朵   附言:好帖.
2022-03-14 11:09
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:347
专家分:326
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2022-3-14 11:09:53的发言:
“数据类型不匹配”是API参数声明不对,还是结构成员没对准位置。
调用API涉及到结构类型,VFP通常用字符串来表达,易读性差,不好理解,容易搞错。可以将结构封装成一个类,用结构成员名称来表达操作。

DECLARE long SendMessage IN user32 long,long,long,string@
#define WM_USER 0x0400
#define EM_SETPARAFORMAT (WM_USER + 71)
pf = BINTOC(188,"4RS") + BINTOC(256,"4RS") + REPLICATE(0h00,156);
   + BINTOC(500,"4RS") + 0h0000 + BINTOC(4,"1RS") + REPLICATE(0h00,17)
SendMessage(thisform.rich1.Hwnd, EM_SETPARAFORMAT, 0, @pf)
thisform.rich1.seltext = "123456789"+0h0D0A+"abcdefghijk"+0h0D0A+"ABCDEFGHIJK"++0h0D0A


非常感谢吹版!学到了新知识!心头美滋滋,狂喜……
2022-03-14 12:35
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:347
专家分:326
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2022-3-14 11:09:53的发言:
调用API涉及到结构类型,VFP通常用字符串来表达,易读性差,不好理解,容易搞错。可以将结构封装成一个类,用结构成员名称来表达操作。


确实,相对正式的作法是借助vfp2c32(vfp2c32front),将结构体“翻译”成VFP的类,操作起来会比较方便。
……唉,人老了,懒得再去折腾了。其实若有心,通读一遍vfp2c32的源代码,可能就会有相当大的收获!
还是那句话:人老了,不再有年少时的那种冲劲与动力了。
2022-03-14 22:25
快速回复:请教:调用Windows API时,如何正确地传递struct(结构体)参数?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.014308 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved