全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:6295
推到 Plurk!
推到 Facebook!

Delphi 透過 DDE 讀取 YesWin 的即時資訊出現亂碼

答題得分者是:aftcast
bestlong
站務副站長


發表:126
回覆:734
積分:512
註冊:2002-10-19

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-03-20 14:07:00 IP:60.248.xxx.xxx 訂閱
看到網路上有在寫程式讀取下單軟體的即時資訊
想說來試一試結果資料是讀到了不過卻附上亂碼
畫面如下:




[code delphi]
procedure TForm1.FormCreate(Sender: TObject);
begin
ddeClientItem1.Lines.Clear;
ddeClientItem2.Lines.Clear;
ddeClientItem3.Lines.Clear;
ddeClientItem4.Lines.Clear;

ddeClientConv1.ConnectMode := ddeAutomatic;
ddeClientConv1.FormatChars := True;
ddeClientConv1.FormatChars := False;
ddeClientConv1.SetLink('YES','DQ');

DdeClientItemTime.DdeConv := ddeClientConv1;
DdeClientItemTime.DdeItem := 'Time';

ddeClientItem1.DdeConv := ddeClientConv1;
ddeClientItem1.DdeItem := '$TWT.Name';
ddeClientItem2.DdeConv := ddeClientConv1;
ddeClientItem2.DdeItem := '$TWT.Price';

ddeClientItem3.DdeConv := ddeClientConv1;
ddeClientItem3.DdeItem := 'TXF1.Name';
ddeClientItem4.DdeConv := ddeClientConv1;
ddeClientItem4.DdeItem := 'TXF1.Price';
end;

procedure TForm1.DdeClientItemTimeChange(Sender: TObject);
var i: integer;
begin
Label1.Caption := DDEClientItemTime.Text;
Label3.Caption := IntToStr(Length(DDEClientItemTime.Text));
Label8.Caption := '';
for i := 1 to Length(DDEClientItem2.Text) do
begin
Label8.Caption := Label8.Caption ' ' IntToStr(Ord(DDEClientItemTime.Text[i]));
end;
Label8.Caption := Trim(Label8.Caption)
end;

procedure TForm1.ddeClientItem1Change(Sender: TObject);
begin
Edit1.Text := DDEClientItem1.Text;
Label4.Caption := IntToStr(Length(DDEClientItem1.Text));
end;

procedure TForm1.ddeClientItem2Change(Sender: TObject);
var i: integer;
begin
Edit2.Text := ddeClientItem2.Text;
Label5.Caption := IntToStr(Length(DDEClientItem2.Text));

Edit5.Clear;
for i := 1 to Length(DDEClientItem2.Text) do
begin
Edit5.Text := Edit5.Text ' ' IntToStr(Ord(DDEClientItem2.Text[i]));
end;
Edit5.Text := Trim(Edit5.Text);
end;

procedure TForm1.ddeClientItem3Change(Sender: TObject);
begin
Edit3.Text := ddeClientItem3.Text;
Label6.Caption := IntToStr(Length(DDEClientItem3.Text));
end;

procedure TForm1.ddeClientItem4Change(Sender: TObject);
var i: integer;
begin
Edit4.Text := ddeClientItem4.Text;
Label7.Caption := IntToStr(Length(DDEClientItem4.Text));
Edit6.Clear;
for i := 1 to Length(DDEClientItem4.Text) do
begin
Edit6.Text := Edit6.Text ' ' IntToStr(Ord(DDEClientItem4.Text[i]));
end;
end;

[/code]

不知道站友是否有處理的經驗,能開釋一下嗎?
------
http://blog.bestlong.idv.tw/
http://www.bestlong.idv.tw/
http://delphi-ktop.bestlong.idv.tw/
編輯記錄
bestlong 重新編輯於 2009-03-20 14:12:34, 註解 無‧
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-11-30 13:33:27 IP:111.249.xxx.xxx 訂閱
我用BCB6來實作,也是出現相同的內容,哈!
會不會又是UNICODE的問題呢?

不過那些怪怪字好像也是用不到,直接濾掉應該就可以了吧?

===================引 用 bestlong 文 章===================
...43...
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-11-30 16:28:40 IP:210.64.xxx.xxx 訂閱
照我的經驗與看法:

結構體(delphi叫record?)裡的一些char[ ]之類的資料在轉入ansistring時,沒用使用AnsiString(char*,n) 這個方法建構,而使用一般的AnsiString(char*), 就會導致有"垃圾"。 應該不是送來的資料本身有怪字,而是指到自己程式裡的額外的記憶體。所以才有會 tedit? 什麼之類的…還有規則的 垂垂… 應該都是指到不該指的位置造成。

是在server端的處理時可能就轉不正確造成。
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
mephise
高階會員


發表:4
回覆:149
積分:205
註冊:2004-02-09

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-01-06 08:50:35 IP:60.250.xxx.xxx 訂閱
應該不是 Unicode 的問題, 因為畫面顯示一半是正常, 一半是亂碼
如果傳送過來的資料是 Unicode, 而你沒有用 UTF8Decode 函數來處理 (我猜您是用D7或是更早的版本來寫的)
那麼整行都會是亂碼, 不會一半對, 一半不對
所以猜測是 Server 端送來的訊息有問題, 直接切掉就好

------
Mephise Chen
前興德工程師
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2014-05-23 15:50:53 IP:59.120.xxx.xxx 訂閱
過了快四年才找到解……

底下是我使用 Delphi 2009 測出來不會有亂碼的程式片斷:

var myAnsiPChar: PAnsiChar;
begin
myAnsiPChar := DdeClientConv1.RequestData($TWT.Name);
Caption := string(myAnsiPChar);


或許 DdeClientItem 有什麼不為人知的 Bug 吧。

希望這回覆不會太晚...Orz
編輯記錄
GrandRURU 重新編輯於 2014-05-23 16:28:27, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2014-05-24 23:02:03 IP:114.42.xxx.xxx 訂閱

以下是放在我部落格裡的備份
http://aftcast.pixnet.net/blog/post/32351223

RuRu再度燃起追其真正的原因,經三小時以上的研究,終於解開迷題了!!!! 果與我最開始的猜測有相關性 (之前的回覆)
原因:
TDDEClientItem的Text屬性在某些情形下會得到亂碼加在資料的後面。原因追到VCL源碼去後發現,Text的值與下面的函式有關:
procedure TDdeCliItem.StoreData(DdeDat: HDDEData);
var
Len: Longint;
Data: string;
I: Integer;
begin
if DdeDat = 0 then
begin
RefreshData;
Exit;
end;
Data := PChar(AccessData(DdeDat, @Len)); 這裡就是問題的所在/ // len 1
Move(pData^, Result^, len); // data is binary, may contain nulls
Result[len] := #0; 自己在最後面塞值,讚啦SetLength(Data, Len); //! delphi可測。
FCtrl.Lines.Text := Data;
至於改好後,要怎麼來變更delphi的library ? 這又是另一個題目…我認為應該是將ddeman.pas檔照上面改好後,在delphi裡,用install component的功能,選ddeman.pas檔,然後compile,然後會出錯,但沒關係,會得到ddeman.dcu,然後把這個檔去蓋delphi安裝目錄下的那個。請自行試看看。因我沒有delphi,我都是用c builder,故無法驗證後再保證沒錯啦! 請見諒!
結論:
不知這樣的結果算不算是bug? 假使寫server的人,用vc 寫,也注意到要含null一起copy到記憶體區塊,那就不會出事。但,最佳的解法是依DdeAccessData(hData, @Len); 中的len來決定一個正確的字串,而不是依null值的所在位置。(因null值可能是在正確字串後的任何一個地方出現的)。我會找時間去Embarcadero report這個bug?,希望在未來的版本得到修正!

後記:
yeswin這程式的人員,肯定就是我說的沒注意到長度要包含null,才會造成這樣的情形。假使他有注意,那應該也不會出現亂碼附在後面了!

===================引 用 GrandRURU 文 章===================

或許 DdeClientItem 有什麼不為人知的 Bug 吧。

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2014-05-24 23:04:28, 註解 無‧
aftcast 重新編輯於 2014-05-24 23:13:47, 註解 無‧
herbert2
尊榮會員


發表:58
回覆:640
積分:894
註冊:2004-04-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2014-05-25 01:59:27 IP:202.39.xxx.xxx 訂閱

===================引 用 aftcast 文 章===================
....
RuRu再度燃起追其真正的原因,經三小時以上的研究,終於解開迷題了!!!! 果與我最開始的猜測有相關性 (之前的回覆)
....
結論:
不知這樣的結果算不算是bug?

後記:
yeswin這程式的人員,肯定就是我說的沒注意到長度要包含null,才會造成這樣的情形。假使他有注意,那應該也不會出現亂碼附在後面了!


如果 Embarcadero 的團隊有人肯用心 debug,新加坡來的業務經理就不會這麼難為了!

這些深入核心的動作,還是蕭大俠功夫深。
我只能簡單的 trace 一下 if else,但就看到 TCustomGrid 配合 Runtime Themes 新功能時,
有部分變數用錯了,還有些 TWincontrol VCL 元件應該也有類似 bug;
若是自創新元件,還勉強可應付局部修改與擴增,但那麼底層的 bug,真不知要從何改起呀!

網路找到的一些討論:

http://codeverge.com/embarcadero.delphi.non-tech/vcl-bug-affects-many-vcl-componen/1073429
VCL bug affects many VCL components 2009/12/17
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2014-05-25 06:54:41 IP:1.163.xxx.xxx 訂閱
蕭大俠是正解無誤!實在太強大!
===

因為 TDdeCliItem 放在 implementation

建議還是直接 Copy Add Edit DdeMan.pas 到有使用 Dde 元件的專案裡

這樣專案會優先使用專案裡同名的檔案


等哪一天 EMBT 心情好,在某一版 XXXE 修了這個 Bug 後,再刪掉吧


提外話:
目前 富邦e01 也會有這樣的問題,可能是券商的工程師跳槽過去的吧 XD

話說, Debug 的時間快和開發時間比多了,換了新版情況也好不到哪裡去,
所以,按上述的推理,我很認真的懷疑現在在 EMBT 的 RD,或許是 M$ 派過去的 SPY....

===================引 用 aftcast 文 章===================

以下是放在我部落格裡的備份
http://aftcast.pixnet.net/blog/post/32351223

...43...
編輯記錄
GrandRURU 重新編輯於 2014-05-25 06:55:42, 註解 無‧
GrandRURU 重新編輯於 2014-05-25 06:59:02, 註解 無‧
系統時間:2024-03-29 18:22:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!