ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月28日(日) 00:56

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 4 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2008年4月08日(火) 14:15 
オフライン

登録日時: 2008年3月31日(月) 19:04
記事: 11
お住まい: 東京都
前回RS232Cで受信したデータをリストビューに表示するようにしましたが、
そこで次のような問題が起きています。
最初は意図したとおりに表示されるのですが、データを削除し再び受信し、
データを表示させると、lstrcpy で設定したデータが、その直前に記載したデ
ータにも反映されてしまいます。2回目以降 全てこの様な状態です。
abfanに掲載されているコードを元に同じ様な事をさせたところ同様な結果と
なりました。それを見てください。
どのようにすれば回避できるのか、お教え願えないでしょうか。

     A   B   C         A   B   C   
     A0  B0  C0   →   A0  C0  C0
     A1  B1  C1   →   A1  C1  C1
     A2  B2  C2   →   A2  C2  C2
          ↑                  ↑
         最初              2回目以降

     A0~B2は .pszText = "A0"
     C0~C2は lstrcpy(.pszText, Dt0) の様に設定しています。
コード:
' ----------------------------------------------------------------------------
'  イベント プロシージャ
' ----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd

' メモ - 以下の領域を、変数、構造体、定数、関数を宣言するための、
'        グローバル領域として利用することができます。
' ----------------------------------ここから----------------------------------
Dim hList As Long   'リストビューのハンドル

' ----------------------------------ここまで----------------------------------

Sub MainWnd_Destroy()
    T_ListView_DestroyObjects()
    PostQuitMessage(0)
End Sub

Sub MainWnd_CB_EXIT_Click()
    MainWnd_Destroy()
End Sub

Sub MainWnd_Resize(SizeType As Long, cx As Integer, cy As Integer)
    Dim rc As RECT

    GetClientRect(hMainWnd,rc)										'クライアント領域のサイズを取得
    hList=GetDlgItem(hMainWnd,ListView1)							'ListView1のウィンドウ ハンドルを取得
    MoveWindow(hList, 0, 30, rc.right, rc.bottom - 30, 0)			'hListの大きさを変更する
End Sub

Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
    Dim clm As LVCOLUMN

    hList=GetDlgItem(hMainWnd,ListView1)							'リストビューのハンドルを取得
    SendMessage(hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, _
                LVS_EX_FULLROWSELECT or LVS_EX_GRIDLINES)			'リストビューの拡張スタイルを設定
	With clm
        .mask = LVCF_FMT or LVCF_WIDTH or LVCF_TEXT
        .fmt = LVCFMT_CENTER
        .pszText = "A" : .cx = 80									'カラムの設定
        SendMessage(hList,LVM_INSERTCOLUMN,0,VarPtr(clm))
        .pszText = "B" : .cx = 80
        SendMessage(hList,LVM_INSERTCOLUMN,1,VarPtr(clm))
        .pszText = "C" : .cx = 80
        SendMessage(hList,LVM_INSERTCOLUMN,2,VarPtr(clm))
    End With
End Sub

Sub MainWnd_CB_ADD_Click()
    Dim itm As LVITEM
	Dim Dt0[5] As Byte, Dt1[5] As Byte, Dt2[5] As Byte

	lstrcpy(Dt0, "C0")
	lstrcpy(Dt1, "C1")
	lstrcpy(Dt2, "C2")

    With itm
        .mask = LVIF_TEXT
        .iItem = 0 : .iSubItem = 0 : .pszText = "A0"			'アイテムを追加 1行目
        SendMessage(hList,LVM_INSERTITEM,0,VarPtr(itm)) 
        .iItem = 0 : .iSubItem = 1 : .pszText = "B0"
		MessageBox(0,.pszText,"pszText",MB_OK)					'確認の為
        SendMessage(hList,LVM_SETITEM,0,VarPtr(itm))
        .iItem = 0 : .iSubItem = 2 : lstrcpy(.pszText, Dt0)
        SendMessage(hList,LVM_SETITEM,0,VarPtr(itm))

        .iItem = 1 : .iSubItem = 0 : .pszText = "A1"			'アイテムを追加 2行目
        SendMessage(hList,LVM_INSERTITEM,0,VarPtr(itm))
        .iItem = 1 : .iSubItem = 1 : .pszText = "B1"
        SendMessage(hList,LVM_SETITEM,0,VarPtr(itm))
        .iItem = 1 : .iSubItem = 2 : lstrcpy(.pszText, Dt1)
        SendMessage(hList,LVM_SETITEM,0,VarPtr(itm))
        
        .iItem = 2 : .iSubItem = 0 : .pszText = "A2"			'アイテムを追加 3行目
        SendMessage(hList,LVM_INSERTITEM,0,VarPtr(itm))
        .iItem = 2 : .iSubItem = 1 : .pszText = "B2"
        SendMessage(hList,LVM_SETITEM,0,VarPtr(itm))
        .iItem = 2 : .iSubItem = 2 : lstrcpy(.pszText, Dt2)
        SendMessage(hList,LVM_SETITEM,0,VarPtr(itm))
    End With
End Sub

'ラベルの編集が終わった時の処理
Sub MainWnd_ListView1_EndLabelEdit(ByRef nmLVDispInfo As NMLVDISPINFO)
    SendMessage(hList,LVM_SETITEM,0,VarPtr(nmLVDispInfo.item))	'結果の書き戻し      
End Sub

Sub MainWnd_CommandButton1_Click()
	ListView_DeleteAllItems(GetDlgItem(hMainWnd,ListView1))		'アイテムを削除
End Sub


通報する
ページトップ
投稿記事Posted: 2008年4月08日(火) 14:59 
オフライン

登録日時: 2008年3月31日(月) 19:04
記事: 11
お住まい: 東京都
新たに解ったことを追記します。
2回目以降に誤って表示されるデータは、前回にlstrcpyで設定されたデータ
であることが解りました。
2回目は1回目の時の、3回目は2回目の時の、ということです。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2008年4月08日(火) 19:27 
オフライン

登録日時: 2005年5月31日(火) 18:51
記事: 473
お住まい: 新潟県
なんでだろうと思って最初は気付かなかったんですが、コードを一行一行にバラして読んでたら発見しました。
lstrcpy(.pszText, Dt0)に問題ありです。
コード:
Type LVITEM
	mask As DWord
	iItem As Long
	iSubItem As Long
	state As DWord
	stateMask As DWord
	pszText As BytePtr
	cchTextMax As Long
	iImage As Long
	lParam As LPARAM
	iIndent As Long
End Type
pszText As BytePtrの宣言を見てもらえば分かる通り、pszTextは文字列の先頭ポインタを示すだけの変数なので、lstrcpy()関数で直接イジってはいけません。
コード:
Dim lpStr As LPSTR
	lstrcpy(lpStr,"hoge")
こんなコード書くとアクセス違反になりますよね。
件のコードを動かしてみるとアクセス違反にはならないんですが、それは"B0"っていう文字列定数分のメモリが確保されてるからだと思います。
コード:
Dim lpStr As LPSTR
Dim lpsz="B0" As LPCSTR

	lpStr=lpsz
	lstrcpy(lpStr,"C0")

Debug
lpStrの中身を参照して書き換えてるように見えるかもしれませんが、実際はlpszの中身を書き換えてるんですね。
Debugで確認してみると、lpszの中身が"B0"から"C0"になってるのが分かるかと思います。

そんな訳で2回目以降、pszText"B0"を渡してるつもりでも、"C0"を渡していた、と。

lstrcpy()関数を使わずに、そのままDt0のポインタを渡すだけでオーケーです。
コード:
	Dim itm As LVITEM
	Dim Dt0[5] As Byte, Dt1[5] As Byte, Dt2[5] As Byte

	lstrcpy(Dt0, "C0")
	lstrcpy(Dt1, "C1")
	lstrcpy(Dt2, "C2")

	With itm
		.mask = LVIF_TEXT

		.iItem = 0	'アイテムを追加 1行目

		.iSubItem = 0 : .pszText = "A0"
		ListView_InsertItem(hList,itm)

		.iSubItem = 1 : .pszText = "B0"
		ListView_SetItem(hList,itm)

		.iSubItem = 2 : .pszText=Dt0
		ListView_SetItem(hList,itm)

		.iItem = 1	'アイテムを追加 2行目
		
		.iSubItem = 0 : .pszText = "A1"
		ListView_InsertItem(hList,itm)

		.iSubItem = 1 : .pszText = "B1"
		ListView_SetItem(hList,itm)

		.iSubItem = 2 : .pszText=Dt1
		ListView_SetItem(hList,itm)
		
		.iItem = 2	'アイテムを追加 3行目
		
		.iSubItem = 0 : .pszText = "A2"
		ListView_InsertItem(hList,itm)

		.iSubItem = 1 : .pszText = "B2"
		ListView_SetItem(hList,itm)

		.iSubItem = 2 : .pszText=Dt2
		ListView_SetItem(hList,itm)
	End With
ポインタ操作は難しいですね...。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2008年4月09日(水) 09:27 
オフライン

登録日時: 2008年3月31日(月) 19:04
記事: 11
お住まい: 東京都
7さん 詳しく解説していただきありがとうございます。
lstrcpyを使わずに = を使うことは本編の通信プログラムで最初に試したのですが
その時はうまくいきませんでした。何か他に原因があったのだと思います。
今度は、じっくりと1行1行確認しながら詰めていきます。
本当にありがとうございました。


通報する
ページトップ
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 4 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: Google [Bot] & ゲスト[23人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean