我爱builder

C++Builder 程序员博客

typedef struct Obs  //类型定义
{
    int Index;
    …

}

typedef struct ObsList      //类型定义
{
    int Count;//总测站数
    Obs *ets; //数据

    ObsList(int count=0):Count(count){
      ets= count?(new Obs[count]):NULL;
    }
    ~ObsList(){
        if(ets) {delete []ets; ets=NULL;}
        }

    ObsList& operator=(const ObsList& mat)      //重载=,方便赋值
    {
    …
    }

    ObsStation& operator[](int i)const{return ets[i];} //重载[]

}OriObsList;

OriObsList *Obs=new OriObsList(100);
Obs[2].Index      //编译通不过,错误
Obs->ets[2].Index  //编译通过

请问上面一种方式为什么不正确?如何修改类型定义,才能使用上面一种形式?

C/C++ code
[code=C/C++]OriObsList *Obs=new OriObsList(100); //Obs[2].Index 这里实际上是取的Obs这个指针第三个位置的内容 (*Obs)[2].Index = 1000; ShowMessage(Obs->ets[2].Index);

[/code]

C/C++ code
// 直接在栈上创建实例就完事了呗 OriObsList Obs(100); for(int i=0; i<100; ++i) { ShowMessage(Obs[i].Index); }

[Quote=引用 2 楼 unsigned 的回复:]
C/C++ code

C/C++ code
OriObsList *Obs=new OriObsList(100); //Obs[2].Index 这里实际上是取的Obs这个指针第三个位置的内容 (*Obs)[2].Index = 1000; ShowMessage(Obs->ets[2].Index);

[/Quote]
new出来的也就用这种方法了,否则就别用new

C/C++ code
(*Obs)[2].Index = 1000;

支持….楼上(南果梨)说法…..(*Obs)[2].Index = 1000;

  • Filed under: C++ Builder
  • 刚刚接触WebService,
    用下面这个天气预报的WEB服务做了个简单例子,发现一个问题
    http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

    导入的说明文件中有个取所有支持的地区列表的函数,返回一个自定义类型

    class getSupportDataSetResult : public TRemotable {
    private:
      AnsiString      Fs_schema;
    public:
    __published:
      __property AnsiString  s_schema = { read=Fs_schema, write=Fs_schema };
    };

    virtual getSupportDataSetResult* getSupportDataSet() = 0;

    我在CPP中是这样调用的

    getSupportDataSetResult *c;

    c = new getSupportDataSetResult();

    c = service->getSupportDataSet();

    DEBUG下发现c有值,但我不知道如何取里面的值。

    是不是要加XML文件啊,可如何加呢?结构怎么取得呢?

    还有网上那篇 <通过 SOAP 传递自定义类型数据>的服务端是BCB的

    返回的就是一个xml文件,解析内容

    楼上的,给个解析的例子啊

    这个问题看了一下,数据取到了是一个Recordset格式,但是原先有SOAP能不能处理,暂时还不清楚,由于网络的限制,短时间还没办法验证.

    使用XML-RPC相应的东西应该会比较好处理.

    晚上结贴

    刚看了一下大概的东西,这个好象是Microsoft的DataSet格式,Dot Net是直接支持的,但是似乎没有找到Delphi可以解析的东西方,如果必要的话,可能得自己写了.毕竟那是一个Microsoft出来的格式,所以还算是件一劳永逸的事儿.

    up

    引用 3 楼 jaffy 的回复:
    楼上的,给个解析的例子啊

    是一个微软的格式,可能需要自己parse这个返回的字符串

    引用 9 楼 oyljerry 的回复:
    引用 3 楼 jaffy 的回复:
    楼上的,给个解析的例子啊

    是一个微软的格式,可能需要自己parse这个返回的字符串


    在Delphi当中也有解析的框架,只是处理不太了解,所以处理起来还是有复杂度和工作量的.不知道Microsoft SOAPToolKit当中是否有相应的东西,直接取其中的某一部分来完成.

    现在公司的网络受到限制,很是不爽…

  • Filed under: C++ Builder
  • 请教大家一个问题:

        大家知道,在CB中定义线程类的时候直接可以用New|Others|Thread Object来实现,但是,生成的类里的形式如下:

    #ifndef Unit2H
    #define Unit2H
    //—————————————————————————
    #include <Classes.hpp>
    //—————————————————————————
    class TT : public TThread
    {
    private:
    protected:
            void __fastcall Execute();
    public:
            __fastcall TT(bool CreateSuspended);
    };
    //—————————————————————————
    #endif

    问题是:
      现在我想修改一下构造函数,我想将构造函数修改为形如:__fastcall TT(bool CreateSuspended,Handle &handle);

    该怎么办呢?

      我试了一种方法:将类定义的构造函数声明里修改一下入参如上所示,同时,在cpp文件将构造函数的定义也作相同的修改,

    可是,修改了以后编译不通过,希望高手指点,你可以自己定义一个试验一下!

    谢谢!

    C/C++ code
    class TT : public TThread { private: protected: void __fastcall Execute(); public: __fastcall TT(int x,int y,bool CreateSuspended):TThread(CreateSuspended) { } };

    thks,问题已解决!

  • Filed under: C++ Builder
  • 我在线程里自定义了一个消息用PostMessage传递,如下:
    PostMessage(_hNotifyWnd, ON_COM_RECEIVE, (WPARAM)data_buffer, 0);
    其中(WPARAM)data_buffer是这样的:
    char* data_buffer = new char[48];
    std::copy(data_buffer, find_ptr, find_end_ptr+1);//拷贝数据

    请问在下面消息响应函数里怎么样将data_buffer显示出来

    LRESULT __fastcall TForm1::ON_RECEIVE(TMessage &msg)
    {

    在这里怎么样将数据转换,然后在Memo1里显示出来
    Memo1->Lines->Add()
    }

    我在上面试了将msg.WParam强行转换,然后显示,但编译出错,如下:
    char* data_buffer1;
    data_buffer1==(char*)msg.WParam;

    请哪位大侠能帮忙解答一下

    那data_buffer1=(char*)msg.WParam; 能把数据传递过来吗,
    显示的时候在Memo1- >Lines- >Add() 应该怎么写

    那data_buffer1=(char*)msg.WParam; 能把数据传递过来吗,
    显示的时候在Memo1-  >Lines-  >Add() 应该怎么写

    1)可以
    2)直接加就可以

    你编译报什么错误?

    如下:data_buffer是一个动态创建的字符数组
    char* data_buffer = new char[find_end_ptr-find_ptr+1];
    std::copy(data_buffer, find_ptr, find_end_ptr+1);//拷贝数据

    PostMessage(_hNotifyWnd, ON_COM_RECEIVE, (WPARAM)data_buffer, 0);

    LRESULT __fastcall TForm1::ON_RECEIVE(TMessage &msg)
    {
    请问LS你应该怎么处理,在Memo1将它显示出来?
    }

    1. TForm1::ON_RECEIVE 有没有被正确的触发 ?
      我建议你用重载 WndProc 的形式处理自定义消息,这样比较清晰:

    C/C++ code
    class TForm1 : public … { … protected: void __fastcall WndProc(Messages::TMessage &Msg); … } void __fastcall TForm1::WndProc(Messages::TMessage &Msg) { if(Msg.Msg == ON_COM_RECEIVE) { // 处理自定义ON_COM_RECEIVE消息 } TForm::WndProc(Msg); // 默认处理 }

    2. PostMessage时最好附带长度,举例:

    C/C++ code
    char* data_buffer = new char[len]; std::copy(data_buffer, find_ptr, len);//拷贝数据 PostMessage(_hNotifyWnd, ON_COM_RECEIVE, (WPARAM)data_buffer, len);

    3. data_buffer 只能在消息处理函数中释放:

    C/C++ code
    void __fastcall TForm1::WndProc(Messages::TMessage &Msg) { if(Msg.Msg == ON_COM_RECEIVE) { // 处理自定义ON_COM_RECEIVE消息 char *p = (char*)Msg.WParam; Memo1->Lines->Add( AnsiString(p, Msg.LParam) ); delete p; } TForm::WndProc(Msg); // 默认处理 }

    谢谢楼上的 说的比较具体
    我自定义消息响应函数是这样的
    public:
    BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(ON_COM_RECEIVE, TMessage, ON_RECEIVE)
    END_MESSAGE_MAP(TForm)
    LRESULT __fastcall ON_RECEIVE(TMessage& Message);

    LRESULT __fastcall TForm1::ON_RECEIVE(TMessage &msg)
    { }
    我这样应该没问题吧?
    我做的是串口通信那块,需要将data_buffer数据分解开显示
    例如:data_buffer是这样的"\x45\x46\x47\x46\x43\x54\x65"
    存到P后该怎么样分解一个一个显示?

    自己顶一下

    mark

    我觉得既然是动态分配的,应该用SendMessage,它与PostMessage的区别在于前者是消息被处理后才返回。
    你的问题应该是指针转整形时出错,消息响应事件处理时该字符串指针可能已经是空了

    我将PostMessage改成SendMessage了
    现在就是这个问题怎么样处理
    我自定义消息响应函数是这样的
    public:
    BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER(ON_COM_RECEIVE, TMessage, ON_RECEIVE)
    END_MESSAGE_MAP(TForm)
    LRESULT __fastcall ON_RECEIVE(TMessage& Message);

    LRESULT __fastcall TForm1::ON_RECEIVE(TMessage &msg)
    { }
    我这样应该没问题吧?
    我做的是串口通信那块,需要将data_buffer数据分解开显示
    例如:data_buffer是这样的"\x45\x46\x47\x46\x43\x54\x65"
    存到P后该怎么样分解一个一个显示?

    PostMessage,SendMessage 都可以,我前边已经回答过了,
    区别仅在于PostMessage不能立即 delete

    下面的代码就可以将data_buffer的内容加到Memo1中了

    char *p = (char*)Msg.WParam;
    Memo1->Lines->Add( AnsiString(p, Msg.LParam) );

    “分解一个一个显示”是什么意思?

    "\x45\x46\x47\x46\x43\x54\x65“
    这不是一串数据吗,我想将它分解
    一个一个显示
    比如:Memo1- >Lines- >Add( 显示x45 );
    Memo1- >Lines- >Add( 显示x46);
    Memo1- >Lines- >Add( 显示x47);

    ………………………………

    mark

    Memo1-  >Lines->Text = StringReplace();// \ -> CF LF

    还有没有人帮忙看一下

    "\x45\x46\x47\x46\x43\x54\x65“
    这不是一串数据吗,我想将它分解
    一个一个显示
    比如:Memo1-  >Lines-  >Add(  显示x45  ); 
      Memo1-  >Lines-  >Add(  显示x46);
    Memo1-  >Lines-  >Add(  显示x47);

    数据你已经拿到了,需要分开显示自己处理呀

    char  *p  =  (char*)Msg.WParam;
    Memo1- >Lines- >Add(  (AnsiString)"0x"+ IntToHex((unsigned char)p[0], 2)  );
    Memo1- >Lines- >Add(  (AnsiString)"0x"+ IntToHex((unsigned char)p[1], 2)  );
    … …

    Memo1- >Lines->Add( (AnsiString) "0x "+  IntToHex((unsigned  char)p[0],  2) );
    LS 这样显示的结果我调试的好象不对
    应该显示的结果是45,46,47,…………
    调试的结果不对
    还有没有其它的办法?

    如果你直接 

    char  *p  =  (char*)Msg.WParam;
    Memo1- >Lines- >Add(  AnsiString(p,  Msg.LParam)  );

    的话,Memo1 中显示的是什么?

    是  "\x45\x46\x47\x46\x43\x54\x65"
    还是 "EFGFCTe"

    如果是前者,可以这样:

    char  *p  = (char*)Msg.WParam;
    AnsiString s(p, Msg.LParam);
    delete p;

    TStringList *ss = new TStringList();
    ss->Text = AnsiReplaceStr(s, "\\x", "\n");
    Memo1->Lines->AddStrings( ss );
    delete ss;

    如果是后者,用 Behard 的方法。

    不好意思,可能是我没说清楚,我不是想处理一串数据,而是想处理一个一个数据
    我是想这样:
    假如 我有个long data[12] 这里面有十二个数据

    我想通过
    long* data_buffer = new long[12];
    data_buffer =data;
    ::PostMessage(_hNotifyWnd, ON_COM_RECEIVE, (WPARAM)data_buffer, (LPARAM)12)
    传递到
    void __fastcall TForm1::WndProc(Messages::TMessage &Msg)
    {
      if(Msg.Msg == ON_COM_RECEIVE) {

    long *data_buffer1=(long*)msg.WParam;
    Memo1->Lines->Add(String("数据1")+data_buffer1[0]);
    Memo1->Lines->Add(String("数据2")+data_buffer1[1]);
    Memo1->Lines->Add(String("数据3")+data_buffer1[2]);
    ……
    delete data_buffer1
    }
    }
    但像上面如Memo1->Lines->Add(String("数据1")+data_buffer1[0])
    那样显示数据有时正确,但有时是个很大的数据,请问该怎么样处理,能保证正确?

                                                      谢谢

    我把上面的::PostMessage(_hNotifyWnd,  ON_COM_RECEIVE,  (WPARAM)data_buffer,  (LPARAM)12)
    换成下面的
    ::SendMessage(_hNotifyWnd,  ON_COM_RECEIVE,  (WPARAM)data_buffer,  (LPARAM)12)
    显示正确

    请问是怎么回事?

    老大,已经说得很清楚了!
    PostMessage/SendMessage的区别很难懂吗?

    long  data[12]

    long*  data_buffer = new long[12];
    data_buffer = data; // 这是什么意思?数组直接赋值??

    天哪!你到底会不会 c/c++ 啊!懂不懂指针啊!

    建议恶补基本功去…

    Delphi(Pascal) code
    class TForm1 : public … { … protected: void __fastcall WndProc(Messages::TMessage &Msg); … } void __fastcall TForm1::WndProc(Messages::TMessage &Msg) { if(Msg.Msg == ON_COM_RECEIVE) { // 处理自定义ON_COM_RECEIVE消息 } TForm::WndProc(Msg); // 默认处理 }

    受益。。。

    mark

  • Filed under: C++ Builder
  • 我在自定义一个控件的过程中碰到一些问题,无法解决,请大家帮忙:
    //
    // Head File
    //
    class PACKAGE TLabelPanel : public TCustomPanel
    {
    private:
          TLabel *InfoLabel;  // Display the information
          AnsiString FLabelCaption;
          void __fastcall SetLabelCaption(AnsiString value);
          AnsiString __fastcall GetLabelCaption();
        TFont * FLabelFont;
          void __fastcall SetLabelFont(TFont * value);

    protected:
    public:
          __fastcall TLabelPanel(TComponent* Owner);
          __fastcall ~TLabelPanel(void);

    __published:
          __property ParentFont = {default=1};
          __property AnsiString LabelCaption = { read=GetLabelCaption, write=SetLabelCaption};
          __property TFont * LabelFont = { read=FLabelFont, write=SetLabelFont };
    };
    //
    // Implement cpp File
    //
    static inline void ValidCtrCheck(TLabelPanel *)
    {
          new TLabelPanel(NULL);
    }
    //—————————————————————————
    namespace Labelpanel
    {
          void __fastcall PACKAGE Register()
          {
                TComponentClass classes[1] = {__classid(TLabelPanel)};
                RegisterComponents("UNION_TOFD", classes, 0);
          }
    }
    //—————————————————————————
    __fastcall TLabelPanel::TLabelPanel(TComponent* Owner)
          : TCustomPanel(Owner)

    {
              InfoLabel = (TLabel *)new TLabel(ButtomImage);
                InsertControl(InfoLabel);
                FLabelFont = (TFont *)new TFont;
                Assign(FLabelFont);
    }
    __fastcall TLabelPanel::~TLabelPanel(void)
    {
          if (InfoLabel)
                delete InfoLabel;  // Display the information
          if (FLabelFont)
                delete FLabelFont;

    }
    void __fastcall TLabelPanel::SetLabelCaption(AnsiString value)
    {
          if(FLabelCaption != value) {
                FLabelCaption = value;
                InfoLabel->Caption = value;
          }
    }
    AnsiString __fastcall TLabelPanel::GetLabelCaption()
    {
          return FLabelCaption;
    }
    void __fastcall TLabelPanel::SetLabelFont(TFont * value)
    {
          if(FLabelFont != value) {
                FLabelFont = value;
          }
    }
    故障现象:

    属性LabelCaption 在Object Inspector中可以显示,工作正常
    属性LabelFont 在Object Inspector中可以显示,点击提示"Unable to expand",然后程序出错

    疑问:
    TLabel *InfoLabel 是自定义控件里面的一个子控件, 在Object Inspector中可以修改LabelCaption ,
    但是修改该LabelFont属性时就出错"Unable to expand". 不知道为什么?
    另外我很想知道有没有一种更容易的方法直接导出自定义控件里面的子控件(标准控件)的属性,还有事件

  • Filed under: C++ Builder
  • TIniFile 定义的对象引用 ReadString函数
    TIniFile *ini;
    ini->ReadString ( "EMI", "emi_gen_c", "0×18C618C6" );是要做什么呢?
    ini指向一个.ini文件,现在里面的[EMI]下有emi_gen_c=0×18C618C6

    我本以为和VC中的GetPrivateProfileInt类似,认为他是读取ini文件中的"0×18C618C6".
    ReadString ( "EMI", "emi_gen_c", "0×18C618C6" );的第三个参数表示默认值吗?

    ini->ReadString ( "EMI", "emi_gen_b", "0xC0" ).c_str()则是表示指向该字符串的地址?

    Builder第一次用,请个位多指点,谢谢.

    C/C++ code
    // 第3个参数是当读取不到这个值的时候,函数将以这个默认值返回 // 另外这个ReadString函数的返回值就是你读取到的东东,直接搞个变量接收它就ok了

    C/C++ code
    // 第3个参数是当读取不到这个值的时候,函数将以这个默认值返回 // 另外这个ReadString函数的返回值就是你读取到的东东,直接搞个变量接收它就ok了

    C/C++ code
    // 你贴的那个函数是窗体的标准事件函数, // 那个事件是指窗体要显示的时候触发。和VC里面的OnPaint事件差不多的 // 建议你去搞本c++ Builder的书籍看看,系统的学下。

    谢谢,

    這個市readstring 的函數介紹
    virtual AnsiString __fastcall ReadString(const AnsiString Section, const AnsiString Ident, const AnsiString Default);
    最有一個參數是default值
    如果ini文件下[EMI]下有emi_gen_c=0×18C618C6
    可以直接用ReadSectionValues把值讀到StringList裏取name為emi_gen_c的value;

    void __fastcall Text_mem1Form::FormShow(TObject *Sender)

    這個函數是在Form Show出來的時候觸發的事件 可以在裏面寫一些功能 在Form  Show的時候來完成

  • Filed under: C++ Builder
  • 【举例】
    在设计时,分别定义了两个面板组件(TPanel),名称为Panel1、Panel2,之后,如何将他们放在同一组中,或者说,可以用循环的方式对它们进行操作。
    比如可实现为:
    for(int i = 0; i < 2; i++)
    {
        a[i]->Caption = i;  //其中,a[0]代表Panel1,a[1]代表Panel2.
    }

    【补充说明】
    如果在设计时定义一组面板,如下:
    TPanel  *pnl[4];
    那么在Panel上放置其他组件就都需要编程去实现。如果东西多、复杂,就损失了快速开发工具的效率,以及编程可视化带来的直观效果了。当然,改起来也麻烦了。

    可以用重載[] , 來得到你想要的結果:
    class TPanelList
    {
      TComponent *owner ;
      public :
      TPanelList(TComponent *p) owner(p) {}
      TPanel * operator [] (int a)
      {
        for(int i = 0 ; i < owner->ComponentCount ; ++i) {
          TComponent *p = owner->Components[i];
          if(p.Name == "Panel"+IntToStr(a))
            return (TPanel *)p;
        }
        throw Exception("Panel"+IntToStr(a)+" not found !") ;
      }
    }
    使用:
    TPanelList a(this);
    for(int i = 0; i < 2; i++)
    {
      a[i]->Caption = i;  //其中,a[0]代表Panel1,a[1]代表Panel2.
    }

    這個只做示例,不建議寫這樣效率低下的代碼。

    C/C++ code
    //把Panel对象的指针保存到1个数组里面就可以了啊 //如果只是为了统一操作。用遍历Form控件的方法就很简单了 //也不用定义指针数组

    收到!

    一楼的方法 简单地解决了我的问题。当然三楼也是跟一楼一样的思路(第一行)。

    二楼的方法对于 具有良好编程分格、控件统一命名的编程者也是一个遍历查找的思路。

  • Filed under: C++ Builder
  • 例如:
    int row=20;
    int col=10;
    如何定义一个String类型的二维数组String str[row][col],
    如果想给str[row][col]赋值,如何实现?
    for(int i=0;i <row;i++)
    {
      for(int j=0;i <col;j++)
          str[i][j]=j;
    }
    //可以实现这样赋值吗

    你是想建立动态数组吗?

    C/C++ code
    AnsiString* test= new AnsiString[20,10]; for (int i=0;i<20;i++) for (int j=0;j<10;j++) { test[i,j] = IntToStr(i+j); } delete []test;

    如果要自定义长度的:

    C/C++ code
    int a,b; a = 20; b = 10; AnsiString* test= new AnsiString[a,b]; for (int i=0;i<a;i++) for (int j=0;j<b;j++) { test[i,j] = IntToStr(i+j); } delete []test;

    有一种简单的办法可以直接实现:
    int row=20;
    int col=10;
    StringList pList[row][col];
    for(int i=0;i <row;i++)
    {
      for(int j=0;i <col;j++)
          pList[i][j]= "字符串";
    }

    引用 5 楼 yezhichun 的回复:
    有一种简单的办法可以直接实现:
    int row=20;
    int col=10;
    StringList pList[row][col];
    for(int i=0;i <row;i++)
    {
      for(int j=0;i <col;j++)
          pList[i][j]= "字符串";
    }

    能编译通过吗?

    引用 4 楼 yuanreid 的回复:
    如果要自定义长度的:

    C/C++ code
        int a,b;
        a = 20;
        b = 10;
        AnsiString* test= new AnsiString[a,b];
        for (int i=0;i <a;i++)
            for (int j=0;j <b;j++)
            {
                test[i,j] = IntToStr(i+j);
            }

        delete []test;

    该方法有问题,大家不要使用了

    如果简单点,不妨考虑下STL的vector类

    如果你有boost,另我记得boost有个类库叫Tuple好像它支持N维的泛型

    同意楼上的,
    vector < vector <string> > stringArray;
    这种方式相对简单些

  • Filed under: C++ Builder
  • 我放了一个按钮,处理事件如下:
          HCURSOR  pp = LoadCursorFromFile("do.cur");
          Screen->Cursors[crMyCursor] = pp;//crMyCursor是常数,为6
          Chart1->Cursor = crMyCursor;
    之后,我的Chart1的光标没变化,但是pp 不为空,这几句话执行也没问题,
    问题出在哪里啊,救命

    谢谢,我正在试

    TChart的光标要用OriginalCursor
    你用      Chart1->OriginalCursor = crMyCursor; 就可以了

    学习!帮忙顶了!

    还是Keiy强,直接找到TChart的"机关"。楼主忘了偶的暴力代码吧:-)

  • Filed under: C++ Builder
  • java中可以定义行数一定,但列数不定的二维数组,如int i[][]={{1,2,3},{1},{2,3}}那样用起来很方便,不知道c++中要怎么实现那种定义方式,或者类似的数据结构都可以。

    C/C++ code
    int i[][3]={{1,2,3},{1},{2,3}};

    C++中的多维数组,都是整齐的,所以无法定义出那种数据结构。
    但是那样的初始化方式是可以用的,程序会按顺序初始化数组中的元素。

    哦 ,原来不能用阿,我写的程序的数组是不能有多余的项的,麻烦!!

    int i[][]={{1,2,3},{1},{2,3}}

    int i[][]={{1,2,3},{1,0,0},{2,3,0}}
    使用起来会有很大差别?

    如果仅只是使用下标访问可以使用Variant数组吧

    我的程序的数组是对应坐标的,后面加那么多0,那后面的点不就不好弄了吗。Variant数组时什么意思嘛!

    我还是强烈推荐你采用STL的东东

    容器套容器

    C/C++ code
    #include <vector> using namespace std; vector<vector<int> > CubeVector;//二维的

  • Filed under: C++ Builder