System.out.println("またJavaの季節がやってきた!" + 2);
■ このスレッドは過去ログ倉庫に格納されています
去年の今頃Java学習開始するも挫折
しかし不屈の闘志をめらめらと燃やしながら
そびえ立つ岩壁にいどむため、再びこの地にやってきたのだ!
プログラミング歴は独学Cチョビッツ+独学VBA少々
きょうかしょ
https://www.amazon.co.jp/dp/484433638X
スッキリわかるJava入門 第2版 (スッキリシリーズ) >>404をさらにアプデ
private void Form1_Load(object sender, EventArgs e)
{
string str = null;
int x = 0;
int y = 0;
if (File.Exists(Path))
{
using (sr = new StreamReader(Path))
{
str = sr.ReadToEnd();
}
var rgxX = new Regex(@"(^x=)(-?[0-9]+)", RegexOptions.Multiline);
var strX = rgxX.Match(str).Groups[2].Value;
var rgxY = new Regex(@"(^y=)(-?[0-9]+)", RegexOptions.Multiline);
var strY = rgxY.Match(str).Groups[2].Value;
if (int.TryParse(strX, out x) && int.TryParse(strY, out y))
{
this.Left = x;
this.Top = y;
}
else { SetCenter(); }
}
else { SetCenter(); }
var scr = Screen.GetBounds(this);
const double RemainLimit = 0.6;
bool result = true;
result &= (scr.X + scr.Width - this.Left > this.Width * RemainLimit);
result &= (this.Left + this.Width - scr.X > this.Width * RemainLimit);
result &= (scr.Y + scr.Height - this.Top > this.Height * RemainLimit);
result &= (this.Top + this.Height - scr.Y > this.Height * RemainLimit);
if (!result) { SetCenter(); }
void SetCenter()
{
this.Left = (Screen.PrimaryScreen.Bounds.Width - this.Width) / 2;
this.Top = (Screen.PrimaryScreen.Bounds.Height - this.Height) / 2;
}
} >>408
uintは座標がマイナスの場合しか使えないロジックなのでやめやめ
こんな風にした
保存してある座標をそのまま使って一旦フォームを表示させる
もちろんlocation.txtがないとか、数値が想定通りに記録されてない場合はメインモニタ中央へ表示
その上で、フォームがモニタ画面から飛び出し「すぎてる」場合はメインモニタ中央へ移動
RemainLimit = 0.6はフォームの幅・高さの6割がモニタ画面に映っているならOK
それを下回ったらメインモニタ中央へ表示、という定数
これで上下左右・メインモニタ/サブモニタ関係なしにオールマイティにはみ出し補正可
resultのロジックだけど
result = result && (〜〜〜);
でやってたんだけど、もしかしてとおもって
result &= (〜〜〜);
にしたら行けたんでこれにした
要は if を並べて階層深くしたり、条件式が長くなるのが嫌だっただけなんだけど
これはクラスにまとめてこれから作っていくアプリにも使っていこうかなぁ〜 フォームを一旦表示させてから問題あるなら移動させるという2段階の方法を採った理由は
一度に所定の位置へ置こうとすると、scr.X とかがうまく取得できなかったから どうでもいいような部品なんだけど
うまくいったんで満足である
独習はまだしっかり頭にはいってないところがたくさんあるけど
辞書的に使うのにも適してる
今のGUIの入門本しばらくやってから、独習の残り1割ぐらいだけど
まだ読んでない部分読むか
復習も何度かしないといけないな >>403で書いた複数コントロールを束ねる処理についてなんだけど、
今やってる入門本でも紹介されていた
複数のボタンをひとつのハンドラでコントロールする方法を使う
デザイン画面で複数ボタンを選択してから
右下プロパティウィンドウ→イベントタブ→Clickの項目にハンドラ名を入力してEnter
で、Form1に選択した複数ボタンに一括対応するハンドラが自動生成
ここでひとつ問題がある
Form1のこのハンドラを見ただけでは
このハンドラがどのコントロールに対応してるかがわからない
覚えてりゃいいんだけど、またはコメント書いておけばいいとかいう話ではあるんだけど
やはりちゃんとコード上で確認できるべき
そこで、確認方法
左上ソリューションエクスプローラウィンドウ→Form1をクリックして展開
→Form1.Disigner.csをダブルクリックして開く
コード上に
「Windows フォーム デザイナーで生成されたコード」
というregionがあるので左端+をクリックして展開
この中にbutton2に対応する部分がある
//
// button2
//
this.button2.Location = new System.Drawing.Point(13, 13);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(125, 100);
this.button2.TabIndex = 0;
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.buttons_Click);//←ここ
複数ボタン対応ハンドラの名前は「buttons_Click」としたのだが、
button2.Clickにbuttons_Clickハンドラが登録されている
ここからbutton2.Clickがbuttons_Clickメソッドによりコントロールされることがわかる
同じようにbutton3, button4, button5 ・・・・といったbuttons_Clickハンドラにより
コントロールされるボタンのコードにも、buttns_Clickが登録されているのがわかる 複数コントロールを一括してひとつのハンドラにまとめるには
対象となるコントロールをぽちぽちとctrl+左クリすることで選択していくわけだけど
こういう方法によると、対象外のオブジェクトを間違えて選択してしまうことがある
実際に自分がやった間違いとしてこれ↓
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.button10);
this.splitContainer1.Panel2.Controls.Add(this.button7);
this.splitContainer1.Panel2.Controls.Add(this.button4);
this.splitContainer1.Panel2.Controls.Add(this.button9);
this.splitContainer1.Panel2.Controls.Add(this.button6);
this.splitContainer1.Panel2.Controls.Add(this.button3);
this.splitContainer1.Panel2.Controls.Add(this.button8);
this.splitContainer1.Panel2.Controls.Add(this.button5);
this.splitContainer1.Panel2.Controls.Add(this.button2);
this.splitContainer1.Panel2.Click += new System.EventHandler(this.buttons_Click);//←ここ
this.splitContainer1.Size = new System.Drawing.Size(412, 396);
this.splitContainer1.SplitterDistance = 54;
this.splitContainer1.TabIndex = 0;
ボタンの背景にあるパネルを間違えてクリックしてしまい
パネルがbuttons_Clickハンドラの支配下に置かれてしまっている
このままだとボタンではなく背景のパネルをクリックしただけで
buttons_Clickハンドラに記述されている処理が実行されてしまう
パネルが選択されたかどうかは、デザイン画面上は非常にわかりにくく間違いを招きやすい
選択されたオブジェクトが羅列されているウィンドウは見当たらない
注意深くやっていくしかないというところか ところで、>>413のようにミスしてしまった場合の対応なのだが、
実際、どのオブジェクトがどのハンドラの支配下にあるのかは>>412でわかるように
「隠された」コードを見るしかない
しかも、この部分にはこんなコメントが記述されている
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
>>413の「//←ここ」の行を削除すればいいんだろうなということは
今まで貯めた知識で分かってはいるんだけど、本当にいいんだろうかと。
別の方法により、「自動的に」削除させる方法があるんだろうか
まぁよくわからないので、マイクロソフトさんに逆らって勝手にコードを削ることにする
この辺の知識なしでVisualStudioをさわる人はどう処理をしているのか
もう一度対象オブジェクトを全て削除してから自動生成し直しているのかな
なんだかんだこだわって理解しようとしてると、そのうち役に立つもんだ >>412のこれだけど
this.button2.Click += new System.EventHandler(this.buttons_Click);
this.button2.Click += new EventHandler(this.buttons_Click);
だとエラーがでる
コードが記述されているのはForm1のパーシャルクラスなんだけど
Form1.csにはusing System;が記述されているから省略してもいいんじゃないかと思ったのだが
パーシャルクラスであってもファイルが違うなら、冒頭にusing System;入れないと
省略できないようだ
実際にusing記述したら省略してもいけた
ここは基本的にユーザーがいじらない前提でコードが自動生成される場所なので
usingでの省略は逆に足手まといになるのかな イベントドリブンモデルについて再考
>>391なんだけど、こう書き直してもいい
public delegate void MyEventHandler(object sender, EventArgs e);
class Program
{
public event MyEventHandler myEvent = (sender, e) => { }; //←ここ注目
public void handler(object o, EventArgs e)
{
Console.WriteLine("handler called");
}
public static void Main(string[] args)
{
Program target = new Program();
target.myEvent += target.handler;//+= new MyEventHandler(target.handler)も可
target.myEvent(target, EventArgs.Empty);
}
}
独習567ページのコードに含まれているこれ、
public event KeyCommandEventHandler KeyCommand = v => { };
の理解のために比較対象としてあげてみた
独習の方の
v => { }
は空のメソッドを意味する。
= v => { }
により空のメソッドを初期値としてKeyCommandに代入していることになる
そもそもデリゲート型変数であるKeyCommandにはメソッドが入る
int型変数の初期値として 0 を入れることがあるように
デリゲート型変数にラムダ式を使って空メソッドを初期値として代入しているわけだ。
もちろん初期値を代入することは必須ではないので
public event KeyCommandEventHandler KeyCommand;
と書いてもエラーはでない(はずだ!)
同様に、初期値を設定しない>>391のようなコードも問題なく動く(これは確認済)
上で書きなおしたコードは
(sender, e) => { }
を初期値としてデリゲート型変数myEventに代入している
ラムダ式で表したメソッドだ
デリゲートは引数2つと戻り値voidなので、これに対応した形になっている >>417修正
イベントドリブンモデルにおいては、もちろん通常のデリゲートでも同じような事が
言えるのかもしれんが、
いや、もっというと初期値というもの全般について言えることなんだけど
変数に中身が入ってない状態で呼び出されてしまった場合に備えて
やはり空のメソッドでも入れておくべきだ
初期値についてはいろいろルールがあったはずだが忘れたw
調べるのが面倒なのでおいおいということにしよう
クラス変数とローカル変数でも変ってきたはず
とりあえずこれだけは確認した。下のコードはエラーがでる
初期値代入なしで、中身となるメソッドも入れずに実行した場合
public delegate void MyEventHandler(object sender, EventArgs e);
class Program
{
public event MyEventHandler myEvent;
public void handler(object o, EventArgs e)
{
Console.WriteLine("handler called");
}
public static void Main(string[] args)
{
Program target = new Program();
target.myEvent(target, EventArgs.Empty);
}
} VisualStudioでは、ボタンクリックなどで使われるデリゲート型変数の初期値は
どうなっているのか調べてみた
>>412に従って表示されたbutton2.ClickのClickにカーソルを合わせて右クリ
→定義へ移動
public event EventHandler Click;
初期値となる空メソッドは代入されていないように見える
public event EventHandler Click = (sender, e) => { };
こう書き加えてやろうと思ったがもちろん勝手には書き込めないようだ
中身となるメソッド(ハンドラ)が自動生成されて、自動で代入されていくので
初期値がないことによって生じる問題は基本的には起きないと想定した結果か 忘れてた
>>418で、
初期値設定した上で、中身のメソッドを入れなかった場合はエラーなし
何も表示されずに終了
public delegate void MyEventHandler(object sender, EventArgs e);
class Program
{
public event MyEventHandler myEvent = (sender, e) => { }; //初期値代入
public void handler(object o, EventArgs e)
{
Console.WriteLine("handler called");
}
public static void Main(string[] args)
{
Program target = new Program();
//中身メソッド代入しない
target.myEvent(target, EventArgs.Empty);
}
} private void buttons_Click(object sender, EventArgs e)
{
if (((Button)sender).Text == "あたり")
{
MessageBox.Show("あたり!");
}
}
イベントハンドラの第一引数の具体的な使い方
>>395-396では第二引数 e をやったけど
今回は第一引数のsenderについて
使い方は e と同じで、object型になっているので派生クラスにキャストすることで
senderに格納されてるデータを引き出せる
派生クラスの正確な名称は
MessageBox.Show(sender.GetType().ToString());
を一旦置いてみることで取得できる
この場合
System.Windows.Forms.Button
と表示されるので「Button」が派生クラスだと分かる
Javaだとこの辺のデータも e に格納されていたと思う
>>109の e.getComponent() がそれか 派生クラスの名前は
Form1.Designer.csを見ても分かる
this.button2 = new System.Windows.Forms.Button();
ボタンには Buttonクラスのインスタンスが代入されている フォームの大きさを変えたときにボタンとかテキストボックスが自分の思う通りに
追随してサイズを変えたり、または固定されたり・・・といったことをやってた
SplitContainer→FixedPanel, IsSplitterFixed
TableLayoutPanel
などなど・・・
なれないと思った通りにするのに時間かかる イベントハンドラの中で、Form1の座標を取得したいとき、
イベントハンドラに渡されるsenderの実体がForm1の時は問題ない
((Form1)sender).Left
((Form1)sender).Top
senderの実体がButtonの時は同じようにやってもエラーが出る
ButtonなのにForm1型にキャストしようとするからだ
この場合はこうする
((Button)sender).FindForm().Left
((Button)sender).FindForm().Top
Buttonが位置するFormを取得するメソッドFindFormを使えばいい 自分で気に入ったアイコンをexeファイルやフォームに表示できるようになった! TableLayoutPanel内にコントロールを並べてるのを忘れてると
これらコントロールのサイズを変更しようとしたときに動かなくて
あれれれれ
と思う事があるので注意
TableLayoutPanelで1行2列の2セルにそれぞれテキストボックスを置いていたんだけど
2つのテキストボックスの間にSplitterを挟むことでテキストボックスの幅を
ユーザーが自由に変更出来る仕組みにしようとした
上の記述はこの時遭遇したトラブル
TableLayoutPanelのセル内でもコントロール配置場所は、該当するコントロールの
Anchor,Dockプロパティによって影響を受ける
そもそもの話になるが、Splitterを使う場合はTableLayoutPanelは使わないので排除する Splitterを使う時はこれと接するコントロールのDockプロパティの使い方に注意
>>427のように、2つのtextboxを横に2つ並べて、その間にSplitterを置く場合、
1つ目の左側に置くtextboxのDockプロパティはLeft
Splitterは自動的にLeftに設定され
2つ目の右側に置くtextboxのDockプロパティはFill ←ここ大事
右側をFillにしないと実行時にSplitterにカーソルを合わせてもカーソル表示が変らないし
幅を変えることもできなかった 入門本にgmailチェッカーが載ってたので作ってみたんだけど
テスト用にあらためてgmailアカウント新規でとろうと思ったら電話番号要求してくんのな
でもってSMSとかで確認するとか
あほらしくなって昔取得したアカウント引っ張り出してきて使うことにした
でも結局gmail側のセキュリティ機能が働いてちゃちなアプリではアクセスできないことがわかったので終了 ツイッター投稿アプリも載ってたので作ろうと思ったのだが
ツイッター側からアプリ作成に必要なAPIキーをもらうために
開発者用アカウントをつくらねばならない
これまた電話番号登録しろと出る
これもいやなのでパスでーす >>415について
プロパティウィンドウでイベントを表示させると、
登録済のイベントがあれば右側にハンドラの名前が表示される
これを右クリ→リセットすればForm1.Designer.csからも該当コードが自動的に削除されるようだ 1.
VisualStudio自体を複数開くことができる
ソリューションはslnファイルから直接ひらくことができるが
複数のslnファイルを順々にクリックしていけばどんどん新しいVisualStudioのウィンドウが開いていく
デザイン画面で、複数の設定がめんどくさそうなコントロールを選択してctrl+c
別のVisualStudioのデザイン画面でctrl+vをすればこぴぺもできる
2.
全然別の話だが、clickイベントとmouseClickイベントの違い
mouseClickはそのまんまだけど、clickイベントは、例えば
ボタンにフォーカスがある時にキーボードでEnterを押すことでもイベント発生可能 グラフィックについて
ざっとみたところ理解しないといけないクラスとして
1.Graphics
2.Image
3.Bitmap
入門本では説明が簡略化しすぎてるので、自分で調べないとダメだ グラフィック関係については一体どこから手を付ければいいのか難しいところだ
そもそも外部から持ってきた画像を表示する方法を明確にしていかないといけなさそうだ
つまりリソースの管理をVisualStudioでどうやっているのかについてだ
画像をフォームに表示する方法として、入門本で初めてやったのはこれだ
PictureBoxというコントロールをフォーム上に置く
フォーカスを当てると右上に表示される三角形から「イメージの選択」
次にローカルリソース→インポートにより外部の画像ファイルを選択して取り込むという流れになる
ここで疑問が出てくる
このインポートされた画像は一体どこに保存されているのだろうか
もちろん作成されたexeの中に入っているのは分かっているのだが
その前段階として該当するソリューションフォルダの中のどこかに
画像ファイルが取り込まれていると考えるのが妥当だろう
しかし探しても、画像ファイル自体は見つからないし、
コードをみても画像ファイルの拡張子からして見当たらない
ここでいろいろ検索してみたところ、どうやら取り込まれた画像ファイルは
拡張子「resx」の「XMLリソースファイル」とやらに格納されているようだ
実際にウィンドウ右上のソリューションエクスプローラーのForm1.csを展開するとForm1.resxがある
これをダブルクリックすると、この中に先ほどインポートした画像が入っているのを確認できる
resxには画像だけではなく、音声や文字列を格納することもできるそうだ
resxを利用しない方法もあるようだが、とりあえず利用する流れでやっていくことにしよう
インポートした画像をForm1.resxの中で選択すると、
pictureBox1.Imageという名前が付けられていることが分かる
画像ファイルとしての拡張子が消えている点に注意しなければならない
pictureBox1.Imageをコードの中から探すと、Form1.Designer.csの中に見つかる
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.pictureBox1 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(412, 450);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
usingを使っていないと長ったらしく非常にわかりにくい と、ここまで書いて気づいたのだが、
入門本で初めてフォームに画像を表示した方法はこの方法ではなかったようだ
具体的にはこうやった
ソリューションエクスプローラのプロジェクト名を右クリック→プロパティ
→左側ペインからリソース選択
中央に表示される白いスペースに外部の画像ファイルをDDして放り込む
すると、>>434でもやったが、pictureBoxの右上三角マーク→イメージの選択
(ここでローカルリソースから外部画像ファイルを選ぶのが>>434の方法だ)
→プロジェクトリソースファイルを選択することで
この中から表示する画像ファイルを選択することができる
この方法によればソリューションフォルダの中に画像ファイルがそのままの形で保存されている
プロジェクト名のフォルダの直下にResourcesフォルダが作られており、この中に保存されている
この方法によるリソースの管理は単純なので>>434の方法より理解しやすいが
せっかくなので>>434の方法についても調べてみることにする (結局分からないかもしれないが >>435の方法についていくつか気づいた点
ソリューションエクスプローラのプロジェクト名を右クリック→プロパティ
→左側ペインからリソース選択
ここで開いているウィンドウだが、>>435で、「白いスペース」と書いたが、実際には
デフォルトでは文字列をリソースとして格納するウィンドウが開いており、白いスペースはない
ここに画像ファイルを放り込めば自動的にイメージ対応のウィンドウに切り替わる
対応するリソースの種類に合わせて手動でウィンドウを切り替えるには、ウィンドウのすぐ上の
項目の一番左側、デフォルトだと「文字列」となっているが、右の逆三角形のマークから
イメージ、アイコン、オーディオなどの選択ができる
白いスペースが表示されるのはイメージの対応ウィンドウとなったときだ
もう一点。
>>435の方法を採った場合に、画像ファイルをpictureBoxに置きたい場合
つまり、一旦リソースとして取り込んだ画像ファイルを実際にコードの中で呼び出して使いたい場合だが
デザイン画面のpictureBoxにフォーカスしたときの右上三角マークからイメージ選択する場合は
対応コードはForm1.Designer.csに自動生成されることになる
そうではなく、自分でハンドラなどから呼び出したい場合はこうする
pictureBox1.ImageLocation = @"C:\Image\aaa.jpg";
ImageLocationプロパティに、画像ファイルをフルパスで指定すればよい
Imageプロパティを使っても指定は可能なようだ
前述のForm1.Designer.csに自動生成されるコードもImageプロパティを使用しているようだ↓
this.pictureBox1.Image = global::TestProject.Properties.Resources.aaa;
//(TestProjectはプロジェクト名)
「global::」はグローバル名前空間のエイリアス、独習393ページで一応学習済
この場合なくても動いた
上の一行をusingを使うことで
using TestProject.Properties;
this.pictureBox1.Image = Resources.aaa;
こう書いてもいけた >>434のコードを分析
再度書き直すと、この方法は画像ファイルをForm1.resxというXMLリソースファイルに格納し
ここから画像ファイルを呼び出してpictureBoxに表示させるというものだ
>>434の最後に貼ってあるコードは、アプリを開いた時に該当する画像が表示されるよう
Form1.Designer.csに記述されたものだ。
このコードはコンストラクタを通じてアプリ起動時に読み込まれる
このコードのうち、大事なのは↓の2行
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
これらをusingを使ったとして、部分的に省略すると
ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));//@
this.pictureBox1.Image = ((Image)(resources.GetObject("pictureBox1.Image")));//A
となる。
この2行は、そのままボタンクリックのハンドラに移しても機能する
(↓では変数resourcesはrsに変更)
private void button1_Click(object sender, EventArgs e)
{
var rs = new ComponentResourceManager(typeof(Form1));//@
this.pictureBox1.Image = ((Image)(rs.GetObject("pictureBox1.Image")));//A
}
@についてだが、わからん、なにやらよくわからん
コンストラクタの引数typeof(Form1)はForm1という型に対するTypeオブジェクトだ
「指定した ComponentResourceManager の情報に基づいて、
サテライト アセンブリでリソースを検索する Type を作成します。」
https://docs.microsoft.com/ja-jp/dotnet/api/system.componentmodel.componentresourcemanager?view=netframework-4.7.2
ということらしいんだけど、わからん
ま、とりあえずForm1.resxを探し出すためのものと理解しておこう
Aについてだが、GetObjectは例えば画像以外にも音声などもresxから取得することになるため
戻り値の型はオールマイティーなobjectとなっている
ただし、ここで取得しているのは画像なのでImage型にキャストしている ちょいとまとめると
外部にある画像をリソースとして使うには大きくわけて2つの方法を学んだ
@resxファイルに格納する方法>>434
AResourcesフォルダに格納する方法>>435
そして、どちらにも言える事だが、
アプリ起動時に表示させる場合はForm1.Designer.csに
そのためのコードが自動生成されていることになる
起動後にボタンをクリックするなどによって画像を表示させたいときは
ハンドラ内に自分で記述することになる
ただし、コードの内容は自動生成であろうが自分で記述したものであろうが、
基本的に差異はない https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%83%E3%83%88%E3%83%9E%E3%83%83%E3%83%97%E7%94%BB%E5%83%8F
●ビットマップ画像
ビットマップ画像(ビットマップがぞう、bitmap image / bitmap graphics)とは、
コンピュータグラフィックスにおける画像の表現形式で、ピクセル(画素)を用いたもの。
画像をドットマトリクス状のピクセル群として捉え、
RGB等の表色系に基づいたピクセルの色・濃度の値の配列情報として取り扱う。
●ベクタ画像
これに対し、幾何図形を作成するための情報を数値や式として表現したものをベクタ画像と呼ぶ。 @
継承 Object→MarshalByRefObject→Image→Bitmap
A
http://koshinran.hateblo.jp/entry/2017/06/30/223423
●System.Drawing.Image
ベクタ画像、ビットマップ画像問わず、画像を扱う為のクラス。
png、jpg、gif 等、さまざまな画像形式ファイルを読み書きできる。
●System.Drawing.Bitmap
ビットマップ 画像を扱う為のクラス。
System.Windows.Forms はビットマップベースの GUI 環境なので、
System.Windows.Forms を使った GUI プログラミングでは
Bitmap クラスをよく使用する。
だが、ビットマップに対する図形の描画などは
Graphics クラスを介して行う。
わかりやすいっす
ここでGraphicsが出てくるのですね >>441の@から分かるようにBitmapはImageの派生クラスでビットマップ画像に特化したクラスということになる
じゃ>>437のこれ↓を
private void button1_Click(object sender, EventArgs e)
{
var rs = new ComponentResourceManager(typeof(Form1));
this.pictureBox1.Image = ((Image)(rs.GetObject("pictureBox1.Image")));
}
こう↓書き換えたら・・・(キャスト先の型をImageからBitmapに変更)
private void button1_Click(object sender, EventArgs e)
{
var rs = new ComponentResourceManager(typeof(Form1));
this.pictureBox1.Image = ((Bitmap)(rs.GetObject("pictureBox1.Image")));
}
いけた! 今気づいたんだけど、pictureBoxに画像を設定したりごちょごちょやってると
いつの間にかForm1.resxにあった画像が消えてるというかResourcesフォルダに移ってる・・・?
何らかの連動性があるようだ
この辺については後回しにしていこうとは思うが
こういう現象から導き出される答えは、できるだけResourcesの方を使った方が今のところは安全だということなのかもしれない すでにある画像を読み込んだり、キャンバスを用意したりするのがImageやBitmapクラスで
四角や円や線などを書き込む筆のようなクラスがGraphicsクラスかな
https://so-zou.jp/software/tech/programming/c-sharp/graphics/
Graphicsオブジェクトの取得
3通りの方法が紹介されているが入門本では3つ目の方法を使っている >>444の3通りについてはちゃんとやろうと思う
特に入門本は3つ目の方法でGraphicsを取得しているんだけど
入門本ではImageではなくBitmapを使っている
この辺の違いも明確にしていきたい
ちなみにImageは抽象クラスなのでnewできないが
Bitmapは抽象クラスではないのでnewできる 入門本で玉が跳ね返りながら動くコードを学んだので
高速で跳ね返って動く玉をクリックして捕まえるゲームを作った
クリックのアタリ判定はクリック座標と玉の中心座標の距離を求めてこれが玉の半径以内ならアタリ
イライラするだけのゲームになった JavaでグローバルIPアドレスを毎日記録するアプリを作って
これをタスクスケジューラに登録してあるんだけど、何日か経つと勝手に無効化してしまう
これは一体何が原因なのか
いろいろ調べてみたんだがイマイチわからない
とりあえず正常に動いているタスクの設定を真似して設定を見直してみた
これで動くといいのだが
自分で作ったJavaのプログラムが常時起動しているせいで
タスク実行時にすでに実行中だと判断されてしまっているとか・・・? JavaでグローバルIPアドレスを記録するアプリをつくって
これを毎日起動するようにタスクスケジューラに登録してあるんだけど* 使っているwindowsアプリの入門本は
「作って覚えるVisualC#2017」
なんだけど、VisualStudioの基本操作が紹介されてるという点
どういう流れでアプリをつくっていくのかが分かるという点
この辺がいい
学習の通過点としてこういうテキストは必要だと思う
ただ、このテキスト通りに作っていくと次第に分かっていくんだけど
背後で自動生成されている膨大な量のコードがあるという事
結局これが理解できてないと応用が利かなくなるという点に気づかされる
もちろん俺はまだ一部しか理解できない、というか一部しか見てない
「プログラミング経験ゼロでもしっかりわかる」と銘を打っているんだけど
さすがにこれは言い過ぎ感が否定できない
アマゾンのレビューをみると、誤植を指摘している人がいる
正確にどのページのどの部分かと指摘してるわけではないのだが、
大文字と小文字を間違えてるとかうんぬん
おれはまだ全て読み終えたわけではないが、
ここのことを言っているのではないかと思い当たる部分に出くわした
結論から言うと、誤植ではないと思う
あるフォーム@のボタンを押すことで別のフォームAを一時的に立ち上げるという機能を考える
Aは利用後すぐに閉じられるが、必要な時に何度も立ち上げることになる
このときにAで使うデータを@で作って置いて、
Aを立ち上げるたびに引数を使って渡していきたい
ここで、Aを立ち上げるとは、コード上ではインスタンスを生成することになる
Aクラスのコンストラクタに引数を渡してAインスタンスを生成するのだ
ここで引数がintやstringなら簡単なのだが、
引数自体も自作クラス(CategoryDataSet)のインスタンスなのだ
@の側で引数となるインスタンス内にデータを入れてから、インスタンスごとAに渡す流れなのだ
こうなると
1.@の側で生成する実引数となるインスタンス(categoryDataSet1)
2.Aのコンストラクタでの仮引数(dsCategory)
という2つの変数が登場する
これだけでも初心者は混乱する
さらにだ、Aの側ではdsCategoryとは別に、同じ型の空の変数を用意して、これと
dsCategoryをMergeするという手法を使っている(401ページList2)
この変数が
3.Aの側で用意してある変数(categoryDataSet)
つまりだ、
クラス名CategoryDataSet
@の変数categoryDataSet1
Aの変数categoryDataSet
この3つがごっちゃごちゃになって、別々のものだと理解できず、その結果、
誤植だろこれ!となったのではないかと思う
独習なみにしっかりとした説明があればいいんだけど、背後に生成されるコードについては
ほとんど説明はなく、変数categoryDataSetに至っては、俺の見落としがなければなんだけど、
テキスト内に唐突に出現しているのだ
この変数は、背後で自動生成されているFormItem.Designer.cs内の
InitializeComponentメソッドでnewされているのだが、そんなことに触れようものなら
パンドラの箱をあけるようなもので収拾が付かなくなる
仕方なかったのだろう・・・・・ DataGridViewとDataSet、DataTableの関連についていろいろ調べてた
一体どれがどういう目的で使われているのかとか
なんとなく分かった 引き続き入門本(作って覚えるVisual C#)を読んでるんだけど
DataTableに格納されたデータを取得してこれをcsvファイルに書き込むという場面で
こういうコードがテキスト内に書かれている
foreach (MoneyDataSet.moneyDataTableRow drMoney in moneyDataSet.moneyDataTable)
唐突になにやら面妖なコードが出現
foreachに続く丸括弧内のコードなのだが
普通ここに書くコードの内容を考えると、こう推測できる
@「moneyDataSet.moneyDataTable」 というコレクション(or配列)があって、
A「MoneyDataSet.moneyDataTableRow」 という型の要素が入っている
DataSetはエクセルでいうブック
DataTableはエクセルでいうワークシート
ということらしいので、ワークシートの中の行をコレクションの要素をして扱っているようなイメージか
これぐらいで納得できればいいのだが、じゃ実際にこういう機能、
つまりDataTable内に格納されたデータを取り出す場合に
具体的にどういうコードを書けばいいのかを考えると、この程度の理解では書けないのではないかと思う
そこで、ひとまず@、Aは一体何なのかを実際のコードから読み取ってみよう、と思ったわけだ が、見事に打ち砕かれた
@「moneyDataSet.moneyDataTable」
moneyDataTableがコレクションまたは配列ということであれば、どこかでそういった宣言が
なされているはずだと考えた。もちろん自分でそういったコードを書いた覚えはないので
自動生成されているコードがあるのだろう
そこで、moneyDataTableにカーソルを合わせ右クリ→定義へ移動
するとMoneyDataSetDesigner.cs(これをデザイナと言うそうだ)内に移動する
MoneyDataSetクラスのプロパティとしてmoneyDataTableが定義されているようだ
public moneyDataTableDataTable moneyDataTable {
get {
return this.tablemoneyDataTable;
}
}
これによるとmoneyDataTableを取得すると同じクラス内の変数tablemoneyDataTableが
かえされると・・・もうここでギブアップしたくなるが先に進む
つまり、moneyDataTableはtablemoneyDataTableのゲッターのようなもんで
moneyDataTableの正体はtablemoneyDataTableという認識でいいのか
いや、ゲッターならスペルは同じにして頭文字の大文字小文字変えるだけにしてくれとか
そういうのはなしなんだろうな・・・
取り合えずそういうことみたいなんで、tablemoneyDataTableを同様に右クリ→定義へ移動
すると同じクラス内のここに移動する
private moneyDataTableDataTable tablemoneyDataTable;
「moneyDataTableDataTable」というクラスの変数として宣言されている
この辺のクラス名や変数名をみてると頭が痛くなってくる
moneyDataTableDataTableを右クリ→定義へ移動
public partial class moneyDataTableDataTable : global::System.Data.TypedTableBase<moneyDataTableRow>
ふぅ・・・もうやめたほうがいいのか・・・
これはよくみると同じMoneyDataSetクラスの内部に設けられたインナークラスのようだ
TypedTableBaseクラスを継承している
わからん!
が、このクラスの中をずっと見ていくと、これか・・・と思い当たるメソッドを発見
public moneyDataTableRow this[int index] {
get {
return ((moneyDataTableRow)(this.Rows[index]));
}
}
独習を復習し直さないとこれは理解できない
インデクサーを使っているんだよねこれ
独習441ページのコードと類似点が多い
この辺からコレクション的な何かを「感じる」
これぐらいにしておこうか・・・
俺の実力だとこれ以上やっても理解するまでにメリット以上の時間がかかりそうだ
それより独習をちゃんと復習してもう少しコードを読解する能力を身につけた方がよさそう https://ohke.hateblo.jp/entry/2016/12/03/231909
>・DataSet、DataTable、DataColumn、DataRowを継承したクラスを使う
>・プロパティを介してDataTable、DataColumn、DataRowの値へアクセスできる
デザイナを使った、つまり自動生成されたコードの特徴だそうだ
継承とプロパティを介したアクセス
知識ある人には便利なんだろうが、おれにとってはこの2つが理解を拒む壁となってそびえ立つ
DataSet関連のコードはデザイナを使わなくても組めるので
分からなかったら自分で一から書いていった方が良いのかもしれない
そう思って基礎的なコードをいくつか書いてDataGridViewで表示させてみた
この辺はこれぐらいでいいかと思う
続けていけばそのうち分かることもあるだろう >>452の最後のコードはメソッドではなく、まさにインデクサーそのものか
(再掲)
public moneyDataTableRow this[int index] {
get {
return ((moneyDataTableRow)(this.Rows[index]));
}
}
今、独習のインデクサーのところを見直しているんだけど、
インデクサーはぶっちゃけて言えばインスタンスの配列化をするための技法
つまり、moneyDataTableDataTableクラスのインスタンスを配列化しているといえる
そして、moneyDataTableDataTableクラスのインスタンスがtablemoneyDataTable
で、こいつをそのまま戻り値として返しているのがmoneyDataTableプロパティ
>>451 @「moneyDataSet.moneyDataTable」は
MoneyDataSetクラスのインスタンスmoneyDataSetのプロパティmoneyDataTableであり
これにより上に書いたような流れで、最終的には
moneyDataTableDataTableクラスの配列化されたインスタンスを意味することになる
この配列の要素となっているのが
((moneyDataTableRow)(this.Rows[index]))
であり
簡単にいえば
Rows[ ] の要素となるのだろう
Rowsにカーソルを合わせると
DataTable.Rows このテーブルに属している行のコレクションを取得します
と出てくる。継承元となっているDataTableがここででてくるわけだ
そしてついに、コレクションという言葉にたどり着いた
道が険しく長すぎる
これでいいだろと言いつつ、調べた結果なんとなく分かった気がしてきた
(配列配列といっているが実際にはインデクサーによる配列的ななにかで実際に配列と行って良いのかは知らない) 独習読んでると、いや、こんなの使わないだろ〜
少なくとも自分では使わないよ、とか思うところが結構あるんだけど
デザイナ使った場合、デザイナで自動生成されたコードから
何かを取得して自分のコードで使いたいと思った時、
つまり上に書いたような場合なんだけど、
こういうときに自動生成されたコードが理解できてないと全くコードを書けない
とするとやはり独習レベルの知識は頭に入れておかないとダメなんだろう
道は長いぞ! テキストボックスをデザイナでForm1上に置くことにより自動生成されるコード
テキストボックスのNameプロパティをmyTextBoxとした
特に大事なのはmyTextBoxがTextBoxクラスのインスタンス変数名として「も」利用されているという点。
private System.Windows.Forms.TextBox myTextBox;
//↑Nameへの代入値がそのままインスタンス変数名としても使われる
//
// myTextBox
//
this.myTextBox.Location = new System.Drawing.Point(13, 13);
this.myTextBox.Name = "myTextBox";
this.myTextBox.Size = new System.Drawing.Size(100, 19);
this.myTextBox.TabIndex = 0;
//
// Form1
//
this.Controls.Add(this.myTextBox); StreamReaderを使う時、一行ずつ読み込むとして
whileの繰り返し条件として使う部分
StreamReader sr = new StreamReader(path);
@while (sr.EndOfStream) { }
Awhile (sr.Peek() >= 0) { }
Bwhile (sr.ReadeLine != null) { }
@、Aは正解
Aは少し古い方法で次に読み込む文字のint型整数値(Char型の中身)を返す
読み込む文字がないと「-1」を返すので、0 以上で有る限り、という条件にする
@のEndOfStreamがプロパティであるのに対してPeekはメソッドなので丸括弧忘れないこと
Bはダメ
読み込む行がないとReadLineがnullを返す事を利用しようとしたものだが、これはダメ。
理由は、ReadLineは単純にチェックのために使いたかったのだが、
実際にここで使ってしまうと、読み込み済として一行進めてしまい、
whileブロックの中で読もうと思っていた行を先取りしてしまう
エラーが出るわけではないが使えない
別途変数を用意して使う方法も考えられるが、そこまでしなくても@、Aがあるので・・・ >>451
@「moneyDataSet.moneyDataTable」関連のコードの位置
【moneyDataSet】はForm1.Designer.csで宣言されるインスタンス
private MoneyDataSet moneyDataSet;
↓
【moneyDataTable】はMoneyDataSet.Designer.cs(以下同じ)、MoneyDataSetクラスのプロパティ
public moneyDataTableDataTable moneyDataTable {
get {
return this.tablemoneyDataTable;
}
}
↓
【tablemoneyDataTable】MoneyDataSetクラスのフィールド
private moneyDataTableDataTable tablemoneyDataTable;
↓
【moneyDataTableDataTable】MoneyDataSetクラスのインナークラス
public partial class moneyDataTableDataTable : global::System.Data.TypedTableBase<moneyDataTableRow> { }
↑のインデクサー↓
public moneyDataTableRow this[int index] {
get {
return ((moneyDataTableRow)(this.Rows[index]));
}
}
A「MoneyDataSet.moneyDataTableRow」関連のコードの位置
【MoneyDataSet】MoneyDataSet.Designer.csの中のクラス
public partial class MoneyDataSet : global::System.Data.DataSet { }
↓
【moneyDataTableRow】↑のインナークラス
public partial class moneyDataTableRow : global::System.Data.DataRow { } 頼まれたんでVBAやってるんだけど
VBAでも普通に正規表現使えたのか
知らなかったわ
IEがらみのライブラリかなんか使うみたいだけど
C#で正規表現結構やったんで役に立った VBAに没頭
自分が作ったものじゃないんだけど、あるwebアプリがある
現在ブラウザに表示してる特定のデータをCSVで吐き出す機能を持っている
このCSVからデータをエクセルに取り込んで加工するということをやってる
ただ、
大したデータ量ではないのに、CSVを作らせるのに1分ぐらいかかったりして結構とろい
ローカルで作成するんじゃなくて、鯖に作らせているようだ
そこで、IEによってローカルに取込み済のHTMLを横取りして加工できないかと。
つまり、HTMLスクレイピングをVBAでできないかと思って
ボトルネックになりそうな部分をちょっと触ってみたんだけど、
意外といけそうなんだよなぁ
とりあえず、CSVを使うバージョンを作ってから
暇な時にHTMLスクレイピングやってみようかな メソッドたくさん作ってからどれ使うかあとから決めると頭が整理できていいな
以前はひとつのメソッドを作り込んでたんっだけど
これをやってしまうと、別のメソッドとして切り出した方が
いい機能まで突っ込んでしまって融通が利かなくなる
ちょっとした機能でもどんどん独立させて作る
同じ機能でも少し違うやつが考えられるなら、全部作ってみる
作ってからどれ使うか選びながら組み立てていく
あと、Functionを作ったら、すぐ下にテストのためのメソッドを作っておくと何かと便利 あと、複雑なロジックは紙にシャーペンで書く
絵や図を書き加えながら、コードを書いていく
消しゴムも必須
やっぱ深く考えるにはアナログが一番いい HTMLスクレイピングというかウェブスクレイピングをVBAでやってるんだけど
Dictionaryないかなと思って調べたら、一応使えるようだ
しかし、使ってみたら、ソートの機能すらない
仕方ないので自分で書いてたんだけど、どうもうまく動かない
この原因探しが大変だった
結論から言えば、forのカウンタの部分で最大値を指定するわけだけど
ここに同じforブロックのなかで変化してしまう変数を使ってしまっていた
繰り返し処理の途中で予期せず最大値が変化してしまい、エラーに繋がっていたのだ
VBAのDictionaryで使うソートの機能をネットで調べると、いろいろと洗練されたコードが出てくる
こぴぺの誘惑にかられたのだが、無骨なコードになってしまうとは言えども
この程度自分で書けないのも悔しくて、、あー疲れた 列挙体初めて実戦で使ってみた
これ便利だな
要はbool系は2つしか選択肢ないけど
これをいくつも増やした感じか
switchというかvbaだとselectなんだけど
これにも列挙体使えるし 正規表現をまともに使えるようになるとグンと幅が広がるわぁ 戻り値のないFunctionはSubとどう違うのだろうか ふぅ大体終わったぜ・・・・
今回のVBAプログラムは処理が重くて表示が固まるのが特徴のひとつだった
これをどうやって軽くしていくかが課題
もっと速くなると思うけど、一応固まらないようにはなった C#に戻るとするか・・・とか言いながらVBAに足引っ張られそうだ 昔書いたコードみると書き直したくなるわ
あまりに酷すぎる プログラミングばかりやってたらアジアカップ見るの忘れてたわ
次の試合から録画する
このタイミングで決勝が日韓戦だと妙な盛り上がりを見せそうだ! 凄くがんばってるなぁ・・・頭の下がる思いでみてる。 独習最初から読み直してる
コードかきかきしながら
おれぐらいすぐ忘れる人間はこうでもしないとな
>>473
ぐへへへへへ これからはクラスを作ったらドキュメンテーションコメントを使っていくことにする
///
これ 時間がなくてちょびっとずつしか独習読めないが
これでいいのだ いままでちゃんと覚えてこなかった基本的な事を読み返しながら覚えるようにしてる
例えば値型のサフィックスとか表になって紹介されてるようなやつ vbaでのIE操作に脱線してた
これ面白そうなの作れそうなんだよなぁ null条件演算子
null許容型
三項演算子
null合体演算子
? を使うこいつら if とか switch とかすごく基本的なもの復習した
基本とかいいつつ独習は細かい論点も触れるので忘れてるところもあった ん〜
いろいろ試しているがvbaからhtmlが取得できない いろんなもの作れるようになってきた
IEコントロールおもろいな
VBAだけど 今日もずっとVBAいじってた
リンククリックしてウィンドウを閉じたり開いたりしてると
いろいろエラーが出てくるんだよね
再現性の高いエラーならいんだけど、ネットと関わるエラーはそうじゃないものが多くてやっかい
とりあえずはエラーがでないようなのを作ってみたんだけど
時間を置いて何度も繰り返さないと確信もてない
なぜか時間を置いてからもう一度やるとエラーがおきてたんでその辺気をつけないといけない 新しいウィンドウをIEで開いた時なんかに
開ききる前にIEを捉えようとするとエラーが出る
見た目開いたように見えても読み込みが不十分だったりすることがあるから
IEを掌握する処理をループで回すのがキモとなるようだ CStr と Str の違い
Str()は、符号の1桁分が必ず確保されていて、
数値が正の時の戻り値の頭にはスペース(空白)が入ります。
Cstr()は、プラスのときにスペースは入りません。
これな・・・・これなんだよ
やっと原因見つけたわ windows10だとIE使えないと思ってたんだけど
機能追加でInternet Explorer11が使えるのか
知らなかったわ
ウェブアプリでIE使ってる場合はそのまま移行できるってことかな
その辺勉強してないからわからんが ふ〜む
EdgeをVBAから操作することもできるようだ
でもWebDriverとやらをダウンロード・インストールしないといけない
これができない環境だとやはり厳しいのかもしれない
https://www.ka-net.org/blog/?p=6018
WebDriverを使わない方法もある
https://www.ka-net.org/blog/?p=6033
しかし公式サポートないそうだ 最近VBAでプログラミングするときは
public宣言をできるだけ避けるようにしてる
Subプロシージャはメインとなるひとつだけにして
あとはFunctionを使う
戻り値が欲しいときFunctionの戻り値を使えば良いんだけど
使い勝手が悪いときは、Subプロシージャ内で変数宣言してから
これを参照渡しすることにしてる
昔は大量のPublic宣言された変数があって見通しが悪かったんだけど
この方法に変えてからマシになった感じがする
こういうやり方が正しいかどうかは知らないんだけど windowsのタイムスケジューラってなにが原因かよくわからんけど
いつのまにか無効になってて一日一回設定してあるプログラム起動が
実行しないようになっちゃうのな
設定変えていろいろやってるんだけど、もういっそのことC#で常時起動の何か作って
そこから実行するようにしようかな
常時起動のJavaプログラムもあるからそこからやってもいいんだけどせっかくだし 忙しくてなかなか再開できないわい
また秋ぐらいから再開しようかなぁ
その頃になれば時間ができるだろうから VBA漬け
エラー処理までちゃんと作らないと気が済まなくて
暇な時間がVBAに吸い取られていくのだ 今期は正規表現が使えるようになったのが大きな収穫だった
C#の独習で覚えたんだけどVBAでも使えるんで大活躍
今日はVBAの入力フォームを作らなくてはならぬ 入力フォームのテキストボックスに特殊なデータを貼り付けたいとおもって
SendKeysってのが使ってみたんだけど、今のところうまくテキストボックスに入れることができない
が、その代りに、VBEのコードのカーソルが当たったところに指定した文字列が入力されてるのに気づいた
コードを操作出来ちゃうことになるんだけどどゆことよw 正規表現を使えるようになったとか書いたけど
よくやってしまううっかりミスに気づいた
しかも自分ではそう簡単に間違いだと気づけないやっかいなやつ
アホみたいなミスなんだけど
"\d"
"\D"
を
"{\d}"
"{\D}"
と書いてしまう
これまでにも何度もやってて、気づけなくて結局他の表現方法使ってたんじゃないかと思う
ほんとにアホみたいなんだけどなぜか自分では気づけなかった
今回相当時間かけて悩んでようやく気づいたw
たぶんだけど、
"\s"
"\S"
とかでも同じような事をやってたと思う
まじで注意 今作ってる入力用フォームでエンターキー押したときにあるテキストボックスから別のコントロールに
フォーカスが移るのを阻止したいと思っていた
別のコントロール全てにTabStop=Falseを設定すれば実現できるんだけど
それだと別の問題が生じるので、できたら他の方法をとりたかった
そこで、
対象となっているテキストボックスに
MulitiLine = True
EnterKeyBehavior = True
を設定することで解決
このテキストボックスは一時的に入力を受け付けるだけの特別なものなので
表示される内容は問題にならないのでこれでOK
ちなみに、EnterKeyBehaviorプロパティはTextBox内でエンターキーを押した時に
改行する機能を持たせるもの。(デフォルトだとTextBox内での改行はctrl+Enter) KeyDownのプロシージャを作って、
If KeyCode = vbKeyReturn Then 〜
を記述することでエンターキーの無効化を試みたんだけどこれは失敗だった
Ifブロック自体は働くんだけど、おそらくそのあとに、フォーカスが移る機能が働いてしまうみたいだ
フォーカスが移ったあとに戻す方法もやってみたけど、これは成功した
しかし、フォーカスが移った先のコントロールに影響が波及するのでこれも避けたかった
よって>>501の方法がベスト 上とは関係ないけど
別のところで使えるかもしれないプロパティを見つけたので書いておく
TakeFocusOnClickプロパティ
コントロールがクリックされたときにフォーカスを取得するかどうかを指定します。
True ボタンはクリックされた場合にフォーカスを取得します (既定)。
False ボタンはクリックされた場合にフォーカスを取得しません。 以前つくったものについて高速化を図ろうと思っている
そのうちだけど。
グローバル変数が多い糞仕様を直したいんだけど
ここをいじるとグローバルが故に影響の大きさが怖い
グローバル変数をさわるとしたら、もう一度全部一から作り直す気持でかからないといけない
今のところは、ネストの深い場所で、ワークシート関数へ置換えができないかを考えている
特に、遅くなりがちなセルの値を取得するようなもの
具体的にはforで回しながらIfで一致を試みるようなコードに
Find関数やCountIf関数を使えないか模索したい 二点
・TextBox1_Changeは、テキストボックスに、他のボタンやプログラムを使って
今表示されているものと同じ内容を表示させた場合には働かない
当たり前といえば当たり前だけど、文字列の再入力全てに反応するのではなく
文字列の内容が変化したかどうか、そこに反応する
・Val は文字列を数値に変換する
Valueの略か? TextBoxとかのKeyDownイベントで
Ctrl + c とかを判別する時、
If Shift = 2 and KeyCode = vbKeyC とするのが正解
If KeyCode = vbKeyC and Shift = 2 とするのは不正解
下のコードだとCtrlを押した時点ではCを押していないため
Cを押す前にifブロックをそのまま抜けてしまう
ちょい時間なくて未確認だけどたぶんこうかなと思っている >>506は間違い
どちらもちゃんと機能する
ただしだ、
明日書こう ただしだ、
上に書いた例だと
Ctrl+c の話なんだけど
c だけを押した時も別の機能を持たせたいとする
このときに
If KeyCode = vbKeyC Then
(処理)
ElseIf Shift = 2 And KeyCode = vbKeyC Then
(処理)
End If
とするとctrl+cが働かない
If Shift = 2 And KeyCode = vbKeyC Then
(処理)
ElseIf KeyCode = vbKeyC Then
(処理)
End If
だとうまくいくようだ ■ このスレッドは過去ログ倉庫に格納されています