コンボボックスの編集で苦戦しています

返信する


答えを正確に入力してください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: コンボボックスの編集で苦戦しています

Re: 勘違いでした。すみません。

by 7 » 2006年5月14日(日) 23:59

> C/C++の話でした。m(_ _)m
> 私もABでこれをやろうとしたらエラーして、結局memcpy()を使ったのでした。
C/C++のお話でしたか...ABでも動いたらすごくイイですよねっ!

勘違いでした。すみません。

by 淡幻星 » 2006年5月14日(日) 21:34

> 構造体のキャストってどういうことでしょうか?
>

コード: 全て選択

Dim rc As RECT
> Dim pt As POINTAPI
> 
> 	' ウィンドウの位置をPOINTAPIに代入(コピー)する
> 	' 通常のやり方
> 	GetWindowRect(hMainWnd,rc)
> 	memcpy(VarPtr(pt),VarPtr(rc),SizeOf(POINTAPI))
> 
> 	' ウィンドウの位置をPOINTAPIに代入(コピー)する
> 	' 構造体のキャスト?動かない。
> '	GetWindowRect(hMainWnd,rc)
> '	pt=rc As POINTAPI
> これ動いたら凄くいいと思いました...。
7さん、大変申し訳ない。
私の勘違いでした。

コード: 全て選択

pt = rc As POINTAPI
/* C/C++だと、これで通ったはず。
  pt = (POINTAPI)rc
*/
で、任意の構造体へキャストできるよな~、って思って書いたのですが
それはC/C++の話でした。m(_ _)m
私もABでこれをやろうとしたらエラーして、結局memcpy()を使ったのでした。
失礼いたしました。

by 淡幻星 » 2006年5月13日(土) 19:28

> 余計なことを言ってくれましたね(^_^)
> 構造体のキャストってどういうことでしょうか?
あはは。
ちょっと言い方に語弊がありました。失礼。
「GetMessage?とかで得てきた構造体のポインタ(DWord型)を、
 構造体(RECT型とか)にキャストして使うことがある」って意味でした。
リストビューの処理で、これを使って「あ、コーディングしやすい」って思ったので^^;

時間が合ったら、後でもう少し詳しく書きます。ではでは。

by 7 » 2006年5月13日(土) 19:19

イグトランスさん さんが書きました:> 値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
というよりもこれはInteger型の-1のビットパターンが、ちょうどWord型の65535のビットパターンと一致するからです。
2の補数 - Wikipedia

上位のビットには、おそらく変換先の型が符号付か符号無かによって符号拡張か0拡張を行うはずです。
符号拡張 - Wikipedia
どちらのリンク先も難しくて悩ましいんですけど、各ビットを反転させた値に1を足すと符号の逆転?が出来るってのが驚きというか勉強になりました。
実用的かどうかは...?。

コード: 全て選択

Dim i As Integer
	i=10000
	i=(i Xor &HFFFF)+1	' -10000になる
	' i=-i	' いつもはこうやる
淡幻星さん さんが書きました:つまり、同じ8ビットを使った整数の表現でも、表現方法(=約束事)の違いによって、
ビットが表す値が変わる、ということです。
そこをキチンとやるために型変換(キャスト)が必要、となるわけです。

中略

・・・でも、上記のコードは嘘で(マテ)、実際にはキャストしなくても
「-1→-1」ちゃんと保持(暗示的にキャストしてる)してくれますね。
なるほど。だから値が壊れる現象って起きないんですね。(あんまり?)
淡幻星さん さんが書きました:(個人的には、構造体のキャストくらいしか恩恵感じてなかったり・・・とまた余計なことを言ってみる^^;)。
余計なことを言ってくれましたね(^_^)
構造体のキャストってどういうことでしょうか?

コード: 全て選択

Dim rc As RECT
Dim pt As POINTAPI

	' ウィンドウの位置をPOINTAPIに代入(コピー)する
	' 通常のやり方
	GetWindowRect(hMainWnd,rc)
	memcpy(VarPtr(pt),VarPtr(rc),SizeOf(POINTAPI))

	' ウィンドウの位置をPOINTAPIに代入(コピー)する
	' 構造体のキャスト?動かない。
'	GetWindowRect(hMainWnd,rc)
'	pt=rc As POINTAPI
これ動いたら凄くいいと思いました...。

by イグトランス » 2006年5月13日(土) 11:21

2/4/8バイト整数型には符号付と符号無の両方があるのに、
1バイト整数型だけは符号無のByteしかなく不揃いだったということが、Char型を導入した最大の動機だと思っています。
そしてChar型という名前はC/C++で1バイト符号付整数型と言えばchar型ということからでしょう。
#ちなみにC/C++のchar型は符号付のほうが多い気がしますが、符号の有無はどちらでも良いことになっています。

文字列に対してCharへのポインタや配列を使おうと思っても結局は*Byteとのキャストの山になりいまいち使えないのが個人的には残念です。
#いつかヘッダをいっせいに書き換えてみたいですが互換性のためいつまでもこのままでありそうな気がしてなりません

Re: コンボボックスの編集で苦戦しています

by 淡幻星 » 2006年5月13日(土) 01:24

引き続き蛇足・・・。
新スレを立てるべきかもしれませんね^^;
7さん さんが書きました:> 使ったことの無いChar型についてちょっと調べてみたら、ASCIIコードだけを扱うんですね。
> -128~127なので、マイナスの文字コードがあってそれを操作する為の型なのかと思ってました...。
ちなみに私は、Char型=Byte型だとさっきまで思ってました(^^;)。
文字コード(ASCII)を扱うための変数なのに、なんで符号付にしているのか・・・。
必要なのは0~255なのだから、符号無で良いじゃないかと。
それとも・・・いわゆるアルファベットは0~127の範囲だから、
だったら空いたビットを用いてマイナスも表現しておこう、というノリなのか。
う~ん。分からない(?_?)

7さん さんが書きました:> 値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
いや、「-1」はオーバーフロー(上限値超)の意味じゃないです。
> いや、ご存知じゃないです...どうやるんでしょう。説明をうまく理解できません...。
失礼しました。
えっと・・・
「それぞれの変数型の値の表現法方法が違うのです」って言って伝わるでしょうか?

簡単のために、ビット数が一番小さいChar型(符号あり)、Byte型(符号無し)を例に取ります。
ともに8bitで値を表現します。
Char型は正負の整数を表すための型です。
ここで「マイナスを表現するために最上位のビットを利用する」と約束します。
したがって、最上位を除いた残りの7bitで整数を表現することになります。
その範囲は

コード: 全て選択

000,0000( = 0) ~ 111,1111( = 127)
になります。
これで正の整数は最大127まで表現できました。
では、残りの1ビット(最上位)を使って負の整数を表現することを考えます。
バランス的に、-128くらいまで表現できれば良いですよね。
ならば「最上位のビットはマイナスを意味する」と約束
1000,0000 = 128 → Char型においては「-128」を意味する 
とするわけです。
したがって、

コード: 全て選択

 8ビット         最上位     それ以外のビット
(&H80)
1000,0000 = 1000,0000 + 0000,0000
         = (-128) + 0
         = -128

(&Hf5)
1111,0101 = 1000,0000 + 0111,0101
         = (-128) + 117
         = -10

(&Hff)
1111,1111 = 1000,0000 + 0111,1111
         = (-128) + 127
         = -1

(&H75)
0111,0101 = 0000,0000 + 0111,0101
         = ( 0 ) + 117
         = +117

(&H0a)
0000,1010 = 0000,0000 + 0000,1010
         = ( 0 ) + 10
         = +10
(&H7f)
0111,1111 = 0000,0000 + 0111,1111
         = ( 0 ) + 127
         = +127
と8bitを用いて-128~+127が表現されるわけです。

一方でByte型は、符号無しなので、符号の有無を考える必要が無く、
8ビット全部を使って整数を表現すれば良い。
したがってその範囲は

コード: 全て選択

0000,0000( = 0) ~ 1111,1111( = 255)
になります。

つまり、同じ8ビットを使った整数の表現でも、表現方法(=約束事)の違いによって、
ビットが表す値が変わる、ということです。
そこをキチンとやるために型変換(キャスト)が必要、となるわけです。

コード: 全て選択

Dim b As Byte
Dim c As Char
Dim i As Integer

b = 255 '(=1111,1111)
c = -1 '(=1111,1111)

'仮にキャストしなければ、そのままビットを移すと仮定して
i = b '(0000,0000,1111,1111 = 255)
i = c '(0000,0000,1111,1111 = 255) ※つまり「-1→255」であり、値が壊れた。

i = c As Integer '(1111,1111,1111,1111 = 65535)※キャストすると、値が壊れないようにビットを変えて格納する
/*
Integer型に置いて、-1は「1111,1111,1111,1111=&Hffff」で表現される。
したがって、格納されるビットの内容はcのビットをそのまま移したもの(&H00ff)ではなく、
こちらの&Hffffとなる。これによって「-1→-1」となり、値は壊れない・
*/
・・・でも、上記のコードは嘘で(マテ)、実際にはキャストしなくても
「-1→-1」ちゃんと保持(暗示的にキャストしてる)してくれますね。
わ~い、コンパイラさん賢い~(苦笑)。
むしろ、こっちみたいですね。キャストに意味を持たせようとするならば。

コード: 全て選択

Dim b As Byte
Dim c As Char
Dim i As Integer

b = 255 '(=1111,1111)
c = -1 '(=1111,1111)

i = b '「255」が代入される。
i = c As BYte '「255」が代入される。

i = b As Char '「-1」が代入される。
i = c '「-1」が代入される。
・・・う~ん。キャストの必要性を感じねーな(爆)。
(個人的には、構造体のキャストくらいしか恩恵感じてなかったり・・・とまた余計なことを言ってみる^^;)。

---
追記:
また前後してしましました。今度はイグトランスさんと・・・。
あ~、「符号拡張」って呼ぶんですね。初めて知りました^^;。

by イグトランス » 2006年5月13日(土) 00:50

淡幻星さん さんが書きました:Code:
Dim w As Word
Dim i As Integer

i = &Hffff '「-1」を表す。
w = i As Word '「65535」を表す。
> 値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
というよりもこれはInteger型の-1のビットパターンが、ちょうどWord型の65535のビットパターンと一致するからです。
2の補数 - Wikipedia

符号付整数も符号無整数も所詮はビットの並びです。
そのビットの並びは、プログラマが符号付だと言えば符号付として扱われ符号無だと言えば符号無として扱われます。
それを指示する手段がABなどの言語では型というわけです。

ABの整数型同士の変換の場合、変換先が元より小さければ、
単に下位から変換先の型の大きさのビットパターンを取り出していくはずです。(下位ビットを論理積しているも同然ですね)
逆に変換先が大きければ、下位のビットには元のビットパターンを当てはめ、
上位のビットには、おそらく変換先の型が符号付か符号無かによって符号拡張か0拡張を行うはずです。
符号拡張 - Wikipedia

Re: コンボボックスの編集で苦戦しています

by 7 » 2006年5月13日(土) 00:17

> Char → Long の上位変換を論理演算で表現しようとするとこんな感じなのかな?
>

コード: 全て選択

Dim a As Long
> Dim b As Char
> b = -2
> a = &HFFFFFFFF Xor Not b
> 
>
> *追記
> 上でいけるかと思いましたが、
> Not b の結果がLong型になってないと成立しない計算ですね。
ぅ~ん...どういう処理をしてるのかほとんど分からないですね...。
それにしてもコンボボックスから随分とお話をずらしてしまいました...。

Re: コンボボックスの編集で苦戦しています

by てふろん » 2006年5月12日(金) 23:00

またまた、てふろんです。
まぁ、私の言ってることは揚げ足とりなので、あんまり気にしないで下さい。

Char → Long の上位変換を論理演算で表現しようとするとこんな感じなのかな?

コード: 全て選択

Dim a As Long
Dim b As Char
b = -2
a = &HFFFFFFFF Xor Not b
*追記
上でいけるかと思いましたが、
Not b の結果がLong型になってないと成立しない計算ですね。

テストでは成功したので、書きこみしたのですが、
Not b の結果はChar型なんだけど、それをまた上位変換させてるだけですね。
なんかお馬鹿な書きこみしてすみませんでした。

Re: コンボボックスの編集で苦戦しています

by 7 » 2006年5月12日(金) 22:30

てふろんさん さんが書きました:As演算子と論理演算子では結果は違うと思いますよ。

上はたしかに&HFFを論理積した値と同じになりますが、
下はリテラル値と同じ-1を指しています。

ですので、きちんと型を変換したのち、
Char→Longへの上位変換されていると思います。
なるほど。ビット演算とはちょっと違うんですね

使ったことの無いChar型についてちょっと調べてみたら、ASCIIコードだけを扱うんですね。
-128~127なので、マイナスの文字コードがあってそれを操作する為の型なのかと思ってました...。
淡幻星さん さんが書きました:Code:
Dim w As Word
Dim i As Integer

i = &Hffff '「-1」を表す。
w = i As Word '「65535」を表す。
値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
淡幻星さん さんが書きました:ちなみに、Byte型とChar型を例に取れば、
・Byte型→ビットそのままに、2進法を10進法に変換。
・Char型→最上位ビットはマイナス(&H80=-128)として扱う。それ以外のビットはプラスで扱い、2進数を10進数に変換。
です。・・・って、これはすでにご存知かもしれないですね^^;
いや、ご存知じゃないです...どうやるんでしょう。説明をうまく理解できません...。

Re: コンボボックスの編集で苦戦しています

by 淡幻星 » 2006年5月12日(金) 21:38

ひきつづき、質問内容と違う横スレですが、失礼します。
> 前から思ってたんですけど、結局入るデータは変わらないんですよね?As演算子使っても。
> そうすると使う意味がないような気がします。
> 型が違う物どうしの演算とか代入だってことは明示的になりますけど。
基本的には「明示的にする」以外の意味は無いと思っています。
故に「エラー」ではなく、「警告」なのだと。
私は、普段は無視してますから^^;<型変換の警告

・・・例えばC++だったら、

コード: 全て選択

int a,b;
double d;

a = 5;b=2;

d = a / b // 整数演算として扱われ2.0が格納される。
d = (double)a / b // 浮動小数点演算として扱われ、2.5が格納される。
というように、明示的変換以外の用途もあるんですが。
ABだと、どっちも「2.5」が格納されますね^^;

>上位下位はよく考えたらビット演算すればよさそうですね。
です。

>というか型変換ってビット演算で出来てるんでしょうかね。
みたいです。

コード: 全て選択

Dim b As Byte
Dim n As Long

n = 843
b = n As Byte '下位8bitの「75」が格納される。
b = n '同様に「75」が格納される。
> その時余計に型変換の存在意義が分からなくなりました...。
そういえば、今思い出しました。
こんなときに意味があるかと。

コード: 全て選択

Dim w As Word
Dim i As Integer

i = &Hffff '「-1」を表す。
w = i As Word '「65535」を表す。
すっかり忘れてました(^^;)。


---
投稿が前後してしまったようです(^^;) 以下、追記です。
えっと、てふろんさんが仰っている通りです。
型変換(キャスト)と、ビット演算では代入結果は必ずしも同じになりません。
(普段、キャストを使う場面では「正の整数」ばかりを扱っているので、すっかり忘れていました。)
ちなみに、Byte型とChar型を例に取れば、
・Byte型→ビットそのままに、2進法を10進法に変換。
・Char型→最上位ビットはマイナス(&H80=-128)として扱う。それ以外のビットはプラスで扱い、2進数を10進数に変換。
です。・・・って、これはすでにご存知かもしれないですね^^;

Re: コンボボックスの編集で苦戦しています

by てふろん » 2006年5月12日(金) 21:24

こんにちは、てふろんです。
もともとの質問とは違いますが、ちょっと気になったのでレスします。

全文引用だと長いので一部だけ取り出しての引用にさせていただきました。

> 前から思ってたんですけど、結局入るデータは変わらないんですよね?As演算子使っても。
> というか型変換ってビット演算で出来てるんでしょうかね。

As演算子と論理演算子では結果は違うと思いますよ。

コード: 全て選択


Dim a As Long
a = ( -1 As Byte )
a = ( -1 As Char )
上はたしかに&HFFを論理積した値と同じになりますが、
下はリテラル値と同じ-1を指しています。
Byteにおける&HFFは255ですが、Charにおける&HFFは-1です。
これがバイトに切り出しているだけなら同じ255にならないといけないです。

ですので、きちんと型を変換したのち、
Char→Longへの上位変換されていると思います。

Re: コンボボックスの編集で苦戦しています

by 7 » 2006年5月12日(金) 20:29

> こんなときのことです(と、私は理解しています)。
>

コード: 全て選択

Dim nLong As Long
> Dim nByte As Byte
> 
> nLong = 843 '=&H34b = 0011,0100,1011(2進数)で12bitで表現される
> 
> nByte = nLong '←ここで強制変換の警告が出る
> /* 【理由】
>  Byte型であるnByte には8bitまでしか格納できない。
>  とすると、
>   上位の8bit「0011,0100」(=52=&H34)を格納すればよいのか、
>   下位の8bit「0100,1011」(=75=&H4b)を格納すれば良いのか分からない。
>  どちらにしろ、もともとの値(データ)である「843」とは違う値になってしまう。
>  つまり、データが壊れる。
>  ※普通は、下位のbitが格納されると思います。
> */
>
> なので例えばこの場合は、格納されている数値が255(=&Hff)以下であれば、
>

コード: 全て選択

Dim nLong As Long
> Dim nByte As Byte
> 
> nLong = 75 '=&H4b = 0100,1011(2進数)で8bitで表現される
> 
> nByte = nLong '←ここで強制変換の警告が出るが、問題は無い。
> /* 【理由】
>  もともと8bitまでしかデータが無い。
>  そのまま8bit「0100,1011」(=75=&H4b)を格納するだけ。
>  データは「75」のままであり、壊れない。
> */
> となって、動作上は問題ないわけです。
>
> 警告が出るのは
> 「上に述べたように、データが壊れる可能性がありますが、良いんですか?」
> って意味です。
> As演算子を使うのは
> 「その可能性を分かった上で、壊れないデータ範囲を扱うので、
>  型を変換しても問題ないんですよ。」
> と明示するためです(と、私は理解しています)。
前から思ってたんですけど、結局入るデータは変わらないんですよね?As演算子使っても。
そうすると使う意味がないような気がします。
型が違う物どうしの演算とか代入だってことは明示的になりますけど。
あと、上位8ビットを格納するのか下位8ビットを格納するのか、っていうので思ったんですけど、型変換に上位を格納するのか下位を格納するのか指定するようなことができれば使う意味があると思いました。
あ。上位下位はよく考えたらビット演算すればよさそうですね。

というか型変換ってビット演算で出来てるんでしょうかね。

コード: 全て選択

Dim b As Byte

b=1023 As Byte	' 255が格納
b=(1023 And &FF)	' 255が格納
三日ぐらい前にC++の型変換で面白いコードがあってそれを見た時、型変換ってこんな使い方があるんだっ!って思ったんですけど、ActiveBasicじゃ動かなかったんですよね。
その時余計に型変換の存在意義が分からなくなりました...。
型変換の使い方じゃないって意味では動かない方がいいのかもしれませんけど。
どんな使い方だったかもう忘れちゃったんですけど、「i=(DWORD)*(DWORD)」みたいなコードだったような...。

> 200回記念、おめでとうございます♪(* ^o^)∠.:*:゚☆パン
ありがとうございます(^_^)
詰まらないことですけど、最近数値が綺麗に揃うとむしょうに嬉しくなってしまいます。

Re: コンボボックスの編集で苦戦しています

by 淡幻星 » 2006年5月12日(金) 19:21

横レス失礼します。
7さん さんが書きました:> 支障といえば、データが壊れちゃうことがあるそうです。よく分かりませんけど...。
こんなときのことです(と、私は理解しています)。

コード: 全て選択

Dim nLong As Long
Dim nByte As Byte

nLong = 843 '=&H34b = 0011,0100,1011(2進数)で12bitで表現される

nByte = nLong '←ここで強制変換の警告が出る
/* 【理由】
 Byte型であるnByte には8bitまでしか格納できない。
 とすると、
  上位の8bit「0011,0100」(=52=&H34)を格納すればよいのか、
  下位の8bit「0100,1011」(=75=&H4b)を格納すれば良いのか分からない。
 どちらにしろ、もともとの値(データ)である「843」とは違う値になってしまう。
 つまり、データが壊れる。
 ※普通は、下位のbitが格納されると思います。
*/

なので例えばこの場合は、格納されている数値が255(=&Hff)以下であれば、

コード: 全て選択

Dim nLong As Long
Dim nByte As Byte

nLong = 75 '=&H4b = 0100,1011(2進数)で8bitで表現される

nByte = nLong '←ここで強制変換の警告が出るが、問題は無い。
/* 【理由】
 もともと8bitまでしかデータが無い。
 そのまま8bit「0100,1011」(=75=&H4b)を格納するだけ。
 データは「75」のままであり、壊れない。
*/
となって、動作上は問題ないわけです。

警告が出るのは
「上に述べたように、データが壊れる可能性がありますが、良いんですか?」
って意味です。
As演算子を使うのは
「その可能性を分かった上で、壊れないデータ範囲を扱うので、
 型を変換しても問題ないんですよ。」
と明示するためです(と、私は理解しています)。

※都合上、4bit単位で区切って考えてます。
 もちろん、実際にはLong型は32bit(=4Byte)で表現されているので、
 「843」であれば「0000,0000,0000,0000,0000,0011,0100,1011」として
 格納されています。簡単のため、ゼロのみの部分は省略しました。



追伸:7さんへ。
200回記念、おめでとうございます♪(* ^o^)∠.:*:゚☆パン

Re: コンボボックスの編集で苦戦しています

by 7 » 2006年5月12日(金) 09:58

200回。
電源落とそうと最後に覗いたらいいタイミングですね。

> こちらではリリースコンパイル時に型変換の警告が出ました。
実際に動かしてなかったので忘れてました。

コード: 全て選択

SendMessage(hCombo,CB_GETEDITSEL,VarPtr(Hajime) As WPARAM,VarPtr(Owari) As LPARAM)
> 動いてるから良いかといつも思いますが、修正の仕方がわからずそのままにしていますが、支障があるのでしょうか。
型変換を行うには As演算子 を使います。

コード: 全て選択

Dim cnt As Long
Dim bStr[256] As Byte

	For cnt=0 To 25
		' Long型をByte型に変換
		bStr[cnt]=(Asc("A") + cnt) As Byte
	Next

	MessageBox(hMainWnd,bStr,"アルファベット",MB_OK)
支障といえば、データが壊れちゃうことがあるそうです。よく分かりませんけど...。

ページトップ