#ifディレクティブ

C#にもプリプロセスがある・・・。
#ifディレクティブは、指定されたシンボルが定義されているときに、#endifまでのプログラムがコンパイル対象となる・・・。
C言語C++と違い、マクロの定義ができないので、マクロの値ではなく、シンボルが定義されているかどうかを評価する・・・。

TESTというシンボルが定義されていたら、Console.WriteLineで"Test"と出力する・・・。
そのまま、実行すると、

ABCDE
続行するには何かキーを押してください . . .

定義してないから、"Test"は出力されない・・・。

f:id:BG1:20170309124058p:plain

プロパティから、

f:id:BG1:20170309124131p:plain

[ビルド]の[条件付きコンパイルシンボル]にTESTを追加する・・・。

これで実行すると、

Test
ABCDE
続行するには何かキーを押してください . . .

シンボルが定義されているから、"Test"が出力された・・・。

Sample/cs/ifDirective/ifDirective/src/ifDirective at master · bg1bgst333/Sample · GitHub

#if文

#if文は、プリプロセッサディレクティブのひとつで、指定されたマクロの値が真(true)の時、#endifまでのプログラムが有効となりコンパイル対象となる・・・。
偽(false)の時は、コンパイル対象にならないので、実行もされない・・・。
つまり、コメントアウトと同じようなものだが、これを使うとマクロの値によって条件付きコンパイルができる・・・。

/* ヘッダファイルのインクルード */
#include <stdio.h> /* 標準入出力 */

/* マクロの定義 */
#define SWITCH 0

/* main関数の定義 */
int main(void){

/* SWITCHが真ならコンパイル対象になるので実行される. */
#if SWITCH

  /* "Switch On"と出力 */
  printf("Switch On\n"); /* printfで"Switch On"と出力. */

#endif

  /* "ABCDE"と出力 */
  printf("ABCDE\n"); /* printfで"ABCDE"と出力. */

  /* プログラムの終了 */
  return 0;

}

SWITCHマクロを0にしておく・・・。
"Switch On"を出力する部分はSWITCHが真(つまり0以外)の時、コンパイル対象になるので、

$ gcc if_directive.c -o if_directive
$ ./if_directive
ABCDE
$

実行されない・・・。
しかし、

このようにSWITCHマクロを1にすると、

$ gcc if_directive.c -o if_directive
$ ./if_directive
Switch On
ABCDE
$

となって、"Switch On"の出力が実行された・・・。

Sample/c/if_directive/if_directive/src/if_directive at master · bg1bgst333/Sample · GitHub

#define文

#define文は、プリプロセッサディレクティブのひとつで、プログラム中の指定した文字列を別の文字列に置換する・・・。
こういうのをマクロといい、さまざまなマクロを#define文で定義できる・・・。

今回は数値と文字列の定数マクロを定義する・・・。

INT_TENを10、STR_ABCを"ABC"に置換するマクロを定義・・・。

これで、

このプログラム中のINT_TENは10、STR_ABCは"ABC"に置換される・・・。

実行すると、

$ gcc define.c -o define
$ ./define
i = 10
str = ABC
$

となる・・・。

Sample/c/define/define/src/define at master · bg1bgst333/Sample · GitHub

event

delegate型変数をクラスのメンバフィールドに用意しておけば、コールバック関数を実装できる・・・。
ただ、publicでdelegate型変数を公開すると、直接的に中の関数を実行されてしまう・・・。
かといって、privateにすると、実行するハンドラ関数を登録できない・・・。

eventはdelegate型変数へのアクセスをハンドラ登録のみに限定できる・・・。

InputCheckClass.csを用意し、

引数がstringで戻り値がvoidなdelegate、EventDelegateを定義・・・。
(MainClassからも使うのでpublicにしてる・・・。)

コンストラクタに指定された文字列を格納しておくtarget・・・。
InputCheckClassは、このtargetと同じ文字列が入力されたら、イベントを起こすというクラス・・・。
eventの付いたEventDelegate型変数callback・・・。これがイベント用のデリゲート変数・・・。

引数のtargetをメンバに・・・。

InputCheckLoopで、Console.ReadLineで入力された文字列strがtargetと同じかをチェック・・・。
もし同じなら、strをcallbackに渡して実行、それとともにループを抜ける・・・。
つまり、一致するまで無限ループ・・・。

MainClass.csで、

callbackに登録するハンドラEventHandlerは、こんな感じ・・・。
"Hit!: ~"という感じで入力文字列を出力・・・。

Mainでは、

InputCheckClassオブジェクトchkを生成・・・。
対象文字列は"abc"・・・。
chk.callbackに+=演算子で、EventHandlerを登録・・・。
(chk.callbackに括弧と引数を付けて呼ぼうとするとコンパイルエラーになる・・・。)
chk.InputCheckLoopでチェックループに入る・・・。
一致する文字列が見つかって、ループを抜けたら"(End)"を出力・・・。

hoge
foo
bar
abc
Hit!: abc
(End)
続行するには何かキーを押してください . . .

hoge, foo, barは、abcと一致しないので、EventHandlerの処理は起きない・・・。
しかし、abcを入れると、"Hit!: abc"と出力して、このループは終了・・・。"(End)"が出力されて終わる・・・。

Sample/cs/event/event/src/event_ at master · bg1bgst333/Sample · GitHub

WebSettings.getUserAgentString

WebSettingsのgetUserAgentStringでユーザエージェント文字列を取得できる・・・。

WebSettings | Android Developers

メニューアイテムの切り替えを前回やったので、メニューでユーザエージェントの切り替えができるようにする・・・。

main.xmlは、

menu_change_phoneuaとmenu_change_pcuaを追加・・・。

strings.xmlには、

PhoneとPCを選択できるように・・・。

MainActivity.javaで、

uaTypeを切り替えられるように・・・。
CHROME_PC_UAは前にハードコードしたPC用UA文字列・・・。

最初は電話用UAなので、webSettings.getUserAgentStringで取得したUA文字列をuaTypePhoneStringに・・・。
uaTypePCStringはCHROME_PC_UA・・・。
currentUAにもuaTypePhoneStringを・・・。

onCreateOptionsMenuでも、いちおうメニューアイテムの切り替えの処理・・・。
currentUAがuaTypePhoneStringなら、menu_change_phoneuaを非表示にして、menu_change_pcuaを表示にする・・・。
逆にuaTypePCStringなら、menu_change_pcuaは非表示、menu_change_phoneuaを表示・・・。
(現在の状況と逆の項目を選択できるようにする・・・。ややこしいので注意・・・。)

onPrepareOptionsMenuで、メニューボタンが押された時も、切り替えの処理・・・。

Phoneを選択したら、webSettings.setUserAgentStringでuaTypePhoneStringを設定・・・。
webView.reloadでリロード・・・。
currentUAをuaTypePhoneStringにする・・・。

PCを選択した場合も、uaTypePCStringに設定・・・。
reload・・・。
currentUAをuaTypePCStringに・・・。

f:id:BG1:20170308131221p:plain

Yahoo!をひらく・・・。

f:id:BG1:20170308131243p:plain

電話サイト・・・。
ここでメニューボタンを押すと、

f:id:BG1:20170308131311p:plain

GoBackとPCだけ表示・・・。
PCを選ぶと、

f:id:BG1:20170308131348p:plain

PCサイトに切り替わった・・・。
メニューボタンを押すと、

f:id:BG1:20170308131527p:plain

Phoneに切り替わっているので、これを押すと、

f:id:BG1:20170308131452p:plain

また電話サイトに戻った・・・。

Sample/android/WebSettings/getUserAgentString/src/WebSettings at master · bg1bgst333/Sample · GitHub

Activity.onPrepareOptionsMenu

onPrepareOptionsMenuは、メニューボタン(3点リーダアイコンの)が押された時に発生するハンドラで、メニュー表示前の準備段階の処理を行える・・・。

Activity | Android Developers

最初のアイテムの選択によって以降のメニューアイテムの表示/非表示切り替えができるようにしてみる・・・。

res/menu/main.xmlで、

メニュー切り替えアイテムmenu_changeと、切り替える対象となるアイテムmenu_item_a1~menu_item_b3まで用意・・・。

strings.xmlは、

こんな感じ・・・。

MainActivity.javaで、

定数でMENU_TYPE_AとMENU_TYPE_Bを定義し、menuType変数で切り替える・・・。
onCreateOptionsMenuでは、

最初ここに来るので、B1~B3を非表示にすることで、ChangeとA1~A3だけ表示されるようにする・・・。

onPrepareOptionsMenuでは、

menuTypeがMENU_TYPE_Aの時は、itemB1~itemB3を非表示、itemA1~itemA3を表示・・・。
MENU_TYPE_Bの時は、itemA1~itemA3を非表示、itemB1~itemB3を表示・・・。

onOptionsItemSelectedでmenu_changeなら、menuTypeを切り替える・・・。

f:id:BG1:20170308082611p:plain

右上のメニューボタンを押すと、

f:id:BG1:20170308082651p:plain

ChangeとA1~A3が表示される・・・。B1~B3は非表示・・・。
ここでChangeを選択すると、

f:id:BG1:20170308082746p:plain

閉じるが、再びメニューボタンを押すと、

f:id:BG1:20170308083112p:plain

ChangeとB1~B3に切り替わっている・・・。

B1とかを選択しても、

f:id:BG1:20170308083320p:plain

再びメニューボタンを押すと、切り替わらずにB1~B3のまま・・・。
でも、Changeを押すと、

f:id:BG1:20170308083500p:plain

次にメニューボタン押した時はA1~A3に切り替わっている・・・。

Sample/android/Activity/onPrepareOptionsMenu/src/Activity at master · bg1bgst333/Sample · GitHub

マルチキャストデリゲート

デリゲートには、複数のメソッドを登録できる・・・。
これをマルチキャストデリゲートという・・・。

デリゲートの追加は、

<デリゲート変数> += new <デリゲート名>(<実行するメソッド>)

+演算子や+=演算子を使える・・・。
逆に削除は、

<デリゲート変数> -= <削除対象のみのデリゲート変数>

-演算子や-=演算子を使ったりする・・・。

bracketsにBrackets1を呼ぶデリゲートを登録したら、+=でBrackets2を呼ぶデリゲートを追加登録する・・・。

呼び出しは1回だけ・・・。

で、複数のデリゲートが登録されている場合、呼び出しはすべて行われるが、戻り値の結果は一番最後のものが返される・・・。
なので、

Brackets1、Brackets2、どちらも括弧を付けたあとの文字列をいったん出力している・・・。
そのあと、戻り値として返す・・・。

innerStr = (ABCDE)
innerStr = <ABCDE>
str = <ABCDE>

このように、Brackets1、Brackets2、どちらも呼ばれているが、最終的な戻り値strは後に登録したBrackets2のものになっている・・・。

Sample/cs/MulticastDelegate/MulticastDelegate/src/MulticastDelegate at master · bg1bgst333/Sample · GitHub