C#舐めんなよC#だって出来る子なんだぞ!

低レイヤの文字列操作

なんかC#をバカにされてるようで(←酷い被害妄想)イラっときて書いた。後悔も反省もしない。

 

using System;

class Program {
	unsafe static void Main() {
		string fileName = "hoge.ScR";
		char lc = (char)('a' - 'A');
		fixed(char* p_ = fileName) {
			char* p = p_ + fileName.Length;
			if((*--p | lc) == 'r' && (*--p | lc) == 'c' &&
					(*--p | lc) == 's' && *--p == '.') {
				Console.WriteLine("めっかったぜフォー!");
			}
		}
	}
}

 

IntPtrをbyte*にキャスト出来る

NonSoft – Bitmap処理を高速化するサンプル(C#.NET)

のサンプルの

 

byte* adr = (byte*)_img.Scan0;

 

 

ってコードに驚いた。

何故って、今まで

 

byte[] argbValues = new byte[bmpData.Stride * bmp.Height];
fixed(byte* pixel = &argbValues[0]) {
    byte* pixel_ = pixel;
    Marshal.Copy(bmpData.Scan0, argbValues, 0, argbValues.Length);

 

 

ってな感じで配列にコピーしてからその配列のポインタを操作してたから。

早速コード保管庫のコードに反映させましたよっと。

C#|Bitmap処理の高速化

C#|WebBrowserで表示中のWebページのファビコンを取得

Visual Basic 中学校 掲示板

http://rucio.groupsite.jp/commu/ThreadDetail.aspx?ThreadId=9423

こんなやりとりがありまして。

最初の返信でWikipediaのリンクだけ示したのは、眠くてまともにコードが書けなかったからです。

その後、管理人のるきおさんがコードを書いていたので、僕も書きたくなったわけです。

眠くなかったのでサクっと出来ました。折角なのでC#に書き直してここに記録。

 

using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Windows.Forms;

namespace WindowsFormsApplication1 {
	public partial class Form1:Form {
		public Form1() {
			InitializeComponent();
		}

		private void Form1_Load(object sender, EventArgs e) {
			this.webBrowser1.Navigate("http://blogs.dion.ne.jp/anis7742/");
		}

		private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
			foreach(HtmlElement linkTag in this.webBrowser1.Document.GetElementsByTagName("link")) {
				string relAttribute = linkTag.GetAttribute("rel");
				string iconUrl;
				if(relAttribute == "shortcut icon" || relAttribute == "icon") {
					iconUrl = linkTag.GetAttribute("href");
					if(iconUrl.StartsWith("http")) {        //完全なURLの場合
						this.Icon = getIconFromUrl(iconUrl);
					} else if(iconUrl.StartsWith("/")) {    //絶対パスの場合
						this.Icon = getIconFromUrl("http://" + e.Url.Host + iconUrl);
					} else {                                //相対パスの場合
						this.Icon = getIconFromUrl(e.Url.ToString() + iconUrl);
					}
					break;
				}
			}
			//タグでの指定が無い場合
			this.Icon = getIconFromUrl("http://" + e.Url.Host + "/favicon.ico");
		}

		private Icon getIconFromUrl(string url) {
			using(WebClient webClient = new WebClient())
			using(MemoryStream stream = new MemoryStream(webClient.DownloadData(url))) {
				return new Icon(stream);
			}
		}
	}
}

 

メーラーを電信八号からSylpheedに乗り換えた

メーラーを電信八号からSylpheedに乗り換えた。何故かって?飽きたから。電八で何か不便な点や不満があったわけじゃない。

メーラーの選択の条件

・細かいメールの選別を全てPOPFileに任せているので、ヘッダの内容でメールを振り分けられること。

・1メール1テキストファイルで保存されること。

・軽いこと

・今後の乗り換えに備えてメールのインポート、エクスポート機能があること

で、Sylpheedに決めた。

電八からSylpheedへのメールの変換はちょちょいと以下のようなC#のコードをこさえてサクッと完了。厳密に正しいコードかはわからないけど、上手くいったからよし。

using System.IO;
using System.Text;
class Program {
static void Main(string[] args) {
int fileNumber = 0;
Encoding enc = Encoding.GetEncoding("Shift-Jis");
foreach(string mailFile in Directory.GetFiles(
"電八のメールフォルダ",
"*.txt",
SearchOption.AllDirectories)) {
string mailTxt = File.ReadAllText(mailFile, enc);
mailTxt = mailTxt.Replace("

ちょっとC#でパスワードを覗いてみた。

パスワード入力用のテキストボックスで、入力しても”******”としか表示されないものがありますよね。あれ、不便ですよね。自分で入力したのに見えないなんて理不尽ですよね。

そこで、無理やり入力内容が見える様にするプログラムを書いてみました。Vector辺りを探せばあるような気がするけど気にしたら負けでしょう。

実はアレ、ただのテキストボックスなのでメッセージ投げれば好きなように弄れちゃうんですよね。で、今回投げたのはEM_SETPASSWORDCHAR。EnumChildWindows関数でウィンドウを列挙して手当たり次第にPostMessageしてます。

はい、コードです。

 

using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1 {
    class Program {
        const int EM_SETPASSWORDCHAR = 0xCC;
        delegate int WNDENUMPROC(IntPtr hwnd, int lParam);
        [DllImport("user32.dll")]
        private static extern int EnumChildWindows(
            IntPtr hWndParent, 
            WNDENUMPROC lpEnumFunc, 
            int lParam);
        [DllImport("user32.dll")]
        private static extern int PostMessage(
            IntPtr hwnd, 
            int wMsg, 
            int wParam, 
            int lParam);
        static void Main(string[] args) {
            EnumChildWindows(IntPtr.Zero, EnumWindowsProc, 0);
        }
        static int EnumWindowsProc(IntPtr hWndParent, int lParam) {
            PostMessage(hWndParent, EM_SETPASSWORDCHAR, 0, 0);
            EnumChildWindows(hWndParent, EnumWindowsProc, 0);
            return 1;
        }
    }
}

 

 

これでパスワード丸見えなんですってば。

逆P/Invokeを駆使してTTBaseのプラグインを作れるか?

TTBase http://ttbase.sourceforge.jp/

逆P/Invoke http://www.artonx.org/diary/20081124.html#p01

これでC#でTTBaseのプラグイン作れるんじゃね?と思った。

TTBase.cs TTBaseで使用する構造体とか定数とか

 

using System;
using System.Runtime.InteropServices;
namespace TTBasePlugInTest {
    //プラグインのロードタイプ
    public enum LoadType {
        ptAlwayLoad = 0,
        ptLoadAtUse = 1,
        ptSpecViolation = 0xFFFF
    }
    //メニューに関する定数
    public enum Menu {
        dmNone = 0,
        dmSystemMenu = 1,
        dmToolMenu = 2,
        dmHotKeyMenu = 4,
        dmMenuChecked = 8
    }
    public enum LogOut {
        elNever = 0,
        elError = 1,
        elWarning = 2,
        elInfo = 3,
        elDebug = 4
    }
    [StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]
    public struct PLUGIN_COMMAND_INFO {
        [MarshalAs(UnmanagedType.LPStr)]
        public string Name;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Caption;
        public int CommandID;
        public int Attr;
        public int ResID;
        public int DispMenu;
        public uint TimerInterval;
        public uint TimerCounter;
    }
    [StructLayout(LayoutKind.Sequential,CharSet= CharSet.Ansi)]
    public struct PLUGIN_INFO {
        public ushort NeedVersion;
        [MarshalAs(UnmanagedType.LPStr)]
        public string Name;
        [MarshalAs(UnmanagedType.LPStr)]
        public string FileName;
        public ushort PluginType;
        public uint VersionMS;
        public uint VersionLS;
        public uint CommandCount;
        [MarshalAs(UnmanagedType.LPStruct)]
        public IntPtr Commands;
        //public PLUGIN_COMMAND_INFO Commands;
        public uint LoadTime;
    }
}

 

Class1.cs TTBaseに公開するメソッドを実装

 

using System;
using System.Runtime.InteropServices;
namespace TTBasePlugInTest {
    public class Class1 {
        public static IntPtr TTBEVent_InitPluginInfo(string PluginFilename) {
            PLUGIN_INFO r = new PLUGIN_INFO();
            r.FileName = PluginFilename;
            r.NeedVersion = 0;
            r.Name = "テスト";
            r.PluginType = (int)LoadType.ptAlwayLoad;
            r.CommandCount = 1;
            PLUGIN_COMMAND_INFO pci = new PLUGIN_COMMAND_INFO();
            pci.Name = "test";
            pci.Caption = "てすてす、テストのテストです";
            pci.CommandID = 0;
            pci.DispMenu = (int)(Menu.dmToolMenu | Menu.dmHotKeyMenu);
            IntPtr pciPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pci));
            Marshal.StructureToPtr(pci, pciPtr, false);
            r.Commands = pciPtr;
            //r.Commands = pci;
            IntPtr iPtr = Marshal.AllocHGlobal(Marshal.SizeOf(r));
            Marshal.StructureToPtr(r, iPtr, false);
            return iPtr;
        }
        public static void TTBEvent_FreePluginInfo(IntPtr PluginInfo) {
            Marshal.FreeHGlobal(PluginInfo);
        }
        public static int TTBEvent_Init(string PluginFilename, int hPlugin) {
            return 1;
        }
        public static void TTBEvent_Unload() {
        }
        static int i;
        public static int TTBEvent_Execute(int CommandID, IntPtr hWnd) {
            i++;
            System.Windows.Forms.MessageBox.Show(i.ToString());
            return 1;
        }
        public static void TTBEvent_WindowsHook(int Msg, int wParam, int lParam) {
        }
    }
}

 

上のコードをビルドしたら

 

D:\My Documents\Visual Studio 2008\Projects\TTBasePlugInTest\TTBasePlugInTest\bi
n\Release>ildasm /OUT=TTBasePlugInTest.il TTBasePlugInTest.dll

 

でILにする。

逆P/Invokeを参考にILを編集

 

D:\My Documents\Visual Studio 2008\Projects\TTBasePlugInTest\TTBasePlugInTest\bi
n\Release>c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ilasm.exe /DLL TTBasePlu
gInTest.il
Microsoft (R) .NET Framework IL Assembler.  Version 2.0.50727.3053
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'TTBasePlugInTest.il'  to DLL --> 'TTBasePlugInTest.dll'
Source file is ANSI
Assembled method TTBasePlugInTest.Class1::TTBEVent_InitPluginInfo
Assembled method TTBasePlugInTest.Class1::TTBEvent_FreePluginInfo
Assembled method TTBasePlugInTest.Class1::TTBEvent_Init
Assembled method TTBasePlugInTest.Class1::TTBEvent_Unload
Assembled method TTBasePlugInTest.Class1::TTBEvent_Execute
Assembled method TTBasePlugInTest.Class1::TTBEvent_WindowsHook
Assembled method TTBasePlugInTest.Class1::.ctor
Creating PE file
Emitting classes:
Class 1:        TTBasePlugInTest.Class1
Class 2:        TTBasePlugInTest.PLUGIN_INFO
Class 3:        TTBasePlugInTest.PLUGIN_COMMAND_INFO
Class 4:        TTBasePlugInTest.LoadType
Class 5:        TTBasePlugInTest.Menu
Class 6:        TTBasePlugInTest.LogOut
Emitting fields and methods:
Global
Class 1 Fields: 1;      Methods: 7;
Class 2 Fields: 9;
Class 3 Fields: 8;
Class 4 Fields: 4;
Class 5 Fields: 6;
Class 6 Fields: 6;
Resolving local member refs: 13 -> 13 defs, 0 refs, 0 unresolved
Emitting events and properties:
Global
Class 1
Class 2
Class 3
Class 4
Class 5
Class 6
Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfully

 

とILからDLLを作成。メッセージの意味はよくわからないけど、多分成功してる。

これで出来たDLLをTTBaseのディレクトリにコピーしてTTBaseを起動するも…プラグインとして認識されない。

どこが上手く行ってないのかもわからない状態。

http://twitter.com/takeshik/statuses/2419234928

とか言われたけどC++/CLIとかキモいし。

http://twitter.com/takeshik/statuses/2419254967

とか突っ込まれたけどその通りだと思う。

C#でやることに意味があるのですよ。C#可愛いよ、C#可愛い。

でもC#で出来て無いから何の意味も無いという…。

C#|PropertyGridコントロールに表示されるプロパティ名を変更するには?

PropertyGridコントロールに表示されるプロパティ名を変更するには?

SPDVer 1.74に取り込み完了。

とメモしておけば万一上記リンクが切れてもSPDVer 1.74のコードからサルベージ可能。あにすのコード保管庫に転載するわけにもいかないしね。

あにすのコード保管庫はあにすが書いたコードの保管庫だけど、あにすが書いてないコードも保管したいな。何か良い方法は無いだろうか。公開ブックマーク的なものがあればいいのかな。