Memo2 β版

Memo2 β版を作成します。

前田稔の超初心者のプログラム入門

Form 描画関数

  1. Title.Text, TitleBar, TreeView, RichTextBox の描画を整理します。
    Window 項目 フラグ 説明
    Title.Text 日付 0 作成日付 : 更新日付
    TitleBar ファイル名 0 ファイル名を表示します(m_file)
    Node List 1 Top からの NodeList を表示します
    ファイル名+Title 2 ファイル名+Title を表示します(m_sou)
    TreeView TopNode m_Idx=0 TopNode を開きます
    SelectedNode m_Idx>0 m_Idx の Node を開きます
    ExpandAll 4 全 Node を開きます
    RichTextBox TextBox 0 t_txt[m_Idx]; を表示します
    TextBox * 機密保護が設定されています
    TextBox PWORD * & パスワードのとき解読して表示する
  2. 上の表に従って画面表示を行う FormVier(byte flag) 関数を作成します。
    str = (string)t_ymd[m_Idx]; if (str[str.Length-1]=='*') で機密保護の設定を調べています。
    パスワードがタイプ入力されているときは、暗号化されたテキストを decode(msg) で複合化して表示します。
    機密保護に関係する関数は、このページの後半を参照して下さい。
        // TitleBar, Title, TreeView, RichTextBox の描画
        private void FormView(byte flag)
        {
            string  str;
            Title.Text = (string)t_ttl[m_Idx] + "(" + (string)t_ymd[m_Idx] + ")";
            // Title Bar
            switch(flag&3)
            {
                case 0: this.Text = m_file; break;
                case 1:
                    TreeNode tNode = (TreeNode)t_node[m_Idx];
                    FormView(tNode);
                    break;
                case 2: this.Text = m_sou; break;
            }
            // TreeView
            if ((flag&4)==4)    treeView1.ExpandAll();
            if (m_Idx==0)   treeView1.TopNode.Expand();
            else    treeView1.SelectedNode = (TreeNode)t_node[m_Idx];
            // RichTextBox
            str = (string)t_ymd[m_Idx];
            if (str[str.Length-1]=='*')
            {   if (m_pass!="Decode")
                {   richTextBox1.Text = "☆機密保護が設定されています";
                    return;
                }
                str = (string)t_txt[m_Idx];
                char[] msg = str.ToCharArray();
                decode(msg);
                richTextBox1.Text = new string(msg);
            }
            else    richTextBox1.Text = (string)t_txt[m_Idx];
            richTextBox1.Modified = false;
        }
    
  3. Node のルートを Top からたどり Text に表示する関数です。
        private void FormView(TreeNode pnode)
        {
            TreeNode node;
            m_str = "";
            int i;
            for (node = pnode; node != null; node = node.Parent)
            {
                for (i = 0; i < t_node.Count && (TreeNode)t_node[i] != node; i++) ;
                if (i >= t_node.Count) break;
                m_str = t_ttl[i] + "/" + m_str;
            }
            this.Text = m_str;
            treeView1.SelectedNode = pnode;
            treeView1.Select();
        }
    
  4. RichTextBox に str を設定して key の色を変えて表示する関数です。
    この関数は検索(置換)のときにキーワードを目立つように表示します。
        private void FormView(string str, string key)
        {
            int pos;
            FormView((TreeNode)t_node[m_Idx]);
            this.Text = m_str;
            richTextBox1.Text = str;
            richTextBox1.Select(0, richTextBox1.Text.Length);
            richTextBox1.SelectionColor = Color.Black;
            Title.Text = (string)t_ttl[m_Idx] + "(" + (string)t_ymd[m_Idx] + ") " + m_Idx;
            for (pos = 0; ; )
            {
                pos = richTextBox1.Find(key, pos, RichTextBoxFinds.None);
                if (pos < 0) break;
                richTextBox1.SelectionColor = Color.DarkMagenta;
                pos++;
            }
            richTextBox1.Modified = false;
        }
    
  5. TreeView をクリアして ArrayList に従って TreeView を再登録します。
    この関数は TreeView の Node を削除・挿入したときに呼ばれます。
        private void ReTree_Node(int idx)
        {
            t_node.Clear();
            treeView1.Nodes.Clear();
            m_Idx = 0;
            Set_TVFunc(treeView1, 2);       // TreeView を再登録
            m_Idx = 0;
            if (idx < t_node.Count) m_Idx = idx;
            richTextBox1.Text = (string)t_txt[m_Idx];
            TreeNode node = (TreeNode)t_node[m_Idx];
            FormView(node);
            richTextBox1.Modified = false;
            m_UP = true;
        }
    
  6. treeView1_AfterSelect() では CheckText(); に続いて FormView(0); を呼び出します。
        // Tree View の選択が変更された時の処理
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            CheckText();
            for (m_Idx = 0; m_Idx < t_node.Count && (TreeNode)t_node[m_Idx] != e.Node; m_Idx++);
            if (m_Idx < t_node.Count)
            {
                FormView(0);
            }
        }
    
  7. CheckText() 関数は RichTextBox が修正されたときに t_txt[m_Idx] に保存します。
    機密が設定されているテキストが更新されたときは Encode して格納します。
    t_txt[] には暗号化されたテキストデータを保存します。
        // richTextBox1 を調べて ArrayList を更新
        private void CheckText()
        {
            if (richTextBox1.Modified && (m_Idx<t_txt.Count))
            {
                string str = (string)t_ymd[m_Idx];
                if (str[str.Length-1]!='*') t_txt[m_Idx] = richTextBox1.Text;
                else
                {   if (m_pass=="Decode")
                    {
                        // Encode して t_txt[m_Idx] に格納
                        char[] msg = richTextBox1.Text.ToCharArray();
                        encode(msg);
                        t_txt[m_Idx] = new string(msg);
                    }         
                }
                SetDate(m_Idx);
                m_UP = true;
                richTextBox1.Modified = false;
            }
        }
    
  8. SetDate() 関数でも機密の設定(*)を考慮して下さい。
    機密が設定された Node は、日付の後に * を設定します。
        // 更新日付の設定
        private void SetDate(int idx)
        {
            string ymd, str;
            str = DateTime.Now.ToString();
            ymd = (string)t_ymd[idx];
            if (ymd.Length < 20)    // YYMMDD:YYMMDD
            {
                str = "20" + ymd.Substring(0, 2) + "/" + ymd.Substring(2, 2) + "/"
                      + ymd.Substring(4, 2) + ":" + str.Substring(0, 10);
            }
            else    // YYYY/MM/DD:YYYY/MM/DD 
            {   str = ymd.Substring(0, 11) + str.Substring(0, 10); }
            if (ymd[ymd.Length-1]=='*') str = str + "*";
            t_ymd[idx] = str;
        }
    
  9. HelpAbout() 関数からは FormView(0); で呼び出します。
        private void HelpAbout(object sender, EventArgs e)
        {
            MessageBox.Show("Memo2 Program  β版");
            FormView(0);
        }
    
  10. 他にも FormView() 関数に置き換えた方が良い箇所が幾つかあります。
    特に、この次に説明する「機密保護」を設定すると FormView() を使わなければ支障が出る場合があります。
    FormView() 関数では、機密保護を考慮してプログラミングしています。

機密保護の設定

  1. 暗号化するプログラムでは Pointer を使うので unsafe を設定して下さい。
    unsafe の設定は Pointer を使う を参照して下さい。
    パスワードを間違えると文字化けして判読不能のテキストが表示されます。
    パスワードを間違えたときは、保存しないで終了して下さい。
    間違ったパスワードで保存すると、本当に判読不能になることがあります。
    簡単な機密保護のプログラムなので、保証の限りではありません。
  2. パスワードを入力します。
    検索キーのタイプと共通ですが、m_pass = "PASS"; で識別します。
        string      m_pass = "";                // Pass Word 
    
        // Pass Word の設定
        private void PassWord(object sender, EventArgs e)
        {
            m_pass = "PASS"; 
            richTextBox1.Hide();
            button1.Show();
            textBox1.Show();
        }
    
  3. button_Click() でパスワードを入力します。
    検索キーのタイプと共通ですが、m_pass = "PASS"; で識別します。
    パスワードをキーにして Encode と Decode テーブルを設定します。
        private void button_Click(object sender, EventArgs e)
        {
            m_sou = textBox1.Text;
            m_des = textBox2.Text;
            if (m_pass == "PASS")
            {
                uint wk = 0;
                for (int i = 0; i < m_sou.Length; i++) wk += m_sou[i];
                shuffle(wk);
                for (int i = 0; i < 208; i++) m_dt[m_et[i] - 48] = (byte)(i + 48);
                m_pass = "Decode";
            }
            button1.Hide();
            textBox1.Hide();
            textBox2.Hide();
            richTextBox1.Show();
            FormView(1);
        }
    
  4. 機密保護は Node 単位に設定が可能で、現在の Node にパスワードを設定します。
    パスワードはメモファイル毎に設定可能で、ファイルに含まれる全 Node に共通です。
        private void SetPass(object sender, EventArgs e)
        {
            string str = (string)t_ymd[m_Idx];
            if (str[str.Length - 1] == '*')
            {
                MessageBox.Show("機密保護は設定済みです");
                return;
            }
            if (m_pass == "")
            {
                MessageBox.Show("PassWord を設定して下さい");
                return;
            }
            str = str + "*";
            //Console.WriteLine("yymmdd : " + str);
            t_ymd[m_Idx] = str;
            Title.Text = (string)t_ttl[m_Idx] + "(" + str + ")";
            m_UP = true;
            char[] msg = richTextBox1.Text.ToCharArray();
            encode(msg);
            t_txt[m_Idx] = new string(msg);
            richTextBox1.Text = "機密保護を設定しました";
        }
    
  5. Node のパスワードを解除します。
        private void ResetPass(object sender, EventArgs e)
        {
            string str = (string)t_ymd[m_Idx];
            if (str[str.Length - 1] != '*')
            {
                MessageBox.Show("機密保護は設定されていません");
                return;
            }
            if (m_pass == "")
            {
                MessageBox.Show("PassWord を設定して下さい");
                return;
            }
            str = str.Substring(0, str.Length - 1);
            t_ymd[m_Idx] = str;
            Title.Text = (string)t_ttl[m_Idx] + "(" + str + ")";
            str = (string)t_txt[m_Idx];
            char[] msg = str.ToCharArray();
            decode(msg);
            richTextBox1.Text = new string(msg);
            t_txt[m_Idx] = richTextBox1.Text;
            m_UP = true;
        }
    
  6. 乱数関数と暗号化(Encode)のソースです。
        private uint random(uint n)
        { return (n * 5041 + 13); }
    
        private void shuffle(uint val)
        {
            uint i, j;
            for (i = 0; i < 208; i++) m_et[i] = 0;
            for (i = 0, j = val; i < 208; i++)
            {
                for (j = random(j) % 208; m_et[j] != 0; j = (j + 1) % 208) ;
                m_et[j] = (byte)(i + 48);
            }
            for (i = 0; i < 208 && m_et[i] != 64; i++) ;
            m_et[i] = m_et[16];
            m_et[16] = 64;
        }
    
        // Encode
        unsafe private void encode(char[] msg)
        {
            char    chr;
            byte*   byt;
    
            byt = (byte*)&chr;
            for (int i = 0; i < msg.GetLength(0); i++)
            {
                chr = msg[i];
                e_cvt(byt);
                msg[i] = chr;
            }
        }
        // byte 変換
        unsafe private void e_cvt(byte* pt)
        {
            for (int i = 0; i < sizeof(char); i++)
            {
                if (*(pt + i) >= 48) *(pt + i) = m_et[*(pt + i) - 48];
            }
        }
    
  7. 複合化(Decode) のソースです。
    暗号化/複合化の説明は TEXT の暗号化 TEXT の複合化 を参照して下さい。
        // Decode
        unsafe private void decode(char[] msg)
        {
            char    chr;
            byte*   byt;
    
            byt = (byte*)&chr;
            for (int i = 0; i < msg.GetLength(0); i++)
            {
                chr = msg[i];
                d_cvt(byt);
                msg[i] = chr;
            }
        }
        // decode byte 変換
        unsafe private void d_cvt(byte* pt)
        {
            for (int i = 0; i < sizeof(char); i++)
            {
                if (*(pt + i) >= 48) *(pt + i) = m_dt[*(pt + i) - 48];
            }
        }
    

[Previous Chapter ↑] Memo2 α版

超初心者のプログラム入門(C# Frame Work)