2008年7月2日
#
つぶやき、ですが・・・
.NET Framework 2.0 から追加されました SplitContainer/SplitterPanel が異常に使いにくい。
- SplitContainer.Panel1Collapsed / Panel2Collapsed プロパティでパネルの開閉するって、どうかしてるよ。
- SplitterPanel が sealed クラスなのは、どうかしてるよ。
- SplitterContainer.Panel1 / Panel2 からしか各パネルにアクセスできないって、どうかしてるよ。
- SplitContainer の両方のパネルを閉じられないって、どうかしてるよ。
順を追ってみていきます。
SplitContainer.Panel1Collapsed / Panel2Collapsed プロパティでパネルの開閉するって、どうかしてるよ。
「メソッドでヤラせろよ。」とか、「SplitterPanel.Collapsed プロパティ(internal)を使わせろ。」とか、そういう話。というか、どうして、「Panels」がないんだ! 信じられない!
SplitterPanel が sealed クラスなのは、どうかしてるよ。
あぁ、もう最悪。継承できない。(SplitContainer を継承して、無駄なものを作ることは可能)
SplitterContainer.Panel1 / Panel2 からしか各パネルにアクセスできないって、どうかしてるよ。
我求ム「Panels」。ま、内部的には「Controls」に「Panel1」と「Panel2」が入っているのは知っているけど、いちいちキャストせにゃならんじゃん。いうか、パネル2つしかないのってもったいないよ!
SplitContainer の両方のパネルを閉じられないって、どうかしてるよ。
これ、ちょっと特殊だけど、両方のパネルを閉じたときには、その SplitContainer の親要素が SplitterPanel であれば、その SplitterPanel を閉じて欲しいのよね(そうじゃないときは、例外発生か、閉じられないか)。
以上
2008年6月10日
#
C++/CLIアプリを作成して、ローカライズ(L10N or I18N) します。このとき、もし自分で名前空間を変えているなら、実行時に「System.Resources.MissingManifestResourceException」例外が発生します。
詳細
どうもアセンブリリソースを埋め込む際に、ルート名前空間を見て名前を修飾して埋めているらしく、ローカライズしたフォーム(ApplyResourceを呼びだしている)クラスの名前空間がルート名前空間とずれていると、実行時に適切なリソースを見つけられなくて、「System.Resources.MissingManifestResourceException」例外が発生するようです。
対処方法は2つ。(ま、結局2つともに同じことなんですけど)
- フォームクラスの名前空間を、ルート名前空間に合わせる。
- ルート名前空間を、フォームクラスの名前空間に合わせる。
ルート名前空間は、プロジェクトのプロパティウィンドウ(プロパティページでもプロパティマネージャでもないですよ!)の、ルート名前空間で変更するか、プロジェクトをいったんソリューションエクスプローラからアンロードして、右クリックで編集するなどします。
あぁ、つらい。
2008年6月9日
#
こんな方法は・・・・・・・
using namespace System;
#pragma unmanaged
// コールバック関数の型
typedef int (__stdcall *CallbackFuncType)(int, float);
// コールバック関数
static CallbackFuncType g_func;
// コールバック関数の登録
void SetCallback(CallbackFuncType f)
{
g_func = f;
}
// コールバック関数の呼び出し。
int Run()
{
return g_func(10, 0.5f);
}
#pragma managed
int __stdcall MyFunc(int i, float f)
{
Console::WriteLine(i.ToString());
return static_cast<int>(i * f);
}
int main(array<System::String ^> ^args)
{
// Callback登録(マネージ関数を登録・・)
SetCallback(MyFunc);
// GCしても大丈夫かを確認(登録した関数ポインタがGCされる・・ない)
GC::Collect(2, GCCollectionMode::Forced);
// コールバックをネイティブ関数に呼び出してもらう(GCされてたら死亡)
Int32 ret = Run();
Console::WriteLine(ret.ToString());
return 0;
}
これって、どうなんだろう。実行は問題ないんだけど。。
MSDN「方法 : C++ Interop を使用してコールバックおよびデリゲートをマーシャリングする」とは違う方法で、Marshal::GetFunctionPointerForDelegate() も使わないんだけど・・・。
何かご存じの方、、ヘルプミー。
See Also
2008年5月27日
#
VC2008で、ソースファイルのプロパティで
「詳細」の「コンパイル言語の選択」を「Cコードとしてコンパイル (/TC)」として、
「言語」の「wchar_t をビルトイン型として扱う (/Zc:wchar_t」を「はい」にすると、
wchar_t が組み込み型として使えそうなのに、使えないんですね・・・。
# wchar.hをincludeすれば使えますけど、unsigned short扱いだし、
# CRTを使いたくないのに、wchar.h から crtdefs.h を読み込んじゃうし・・・
C で書くなと??
2008年5月21日
#
ちょっと、ググってみた感じ、世間一般的なバージョン表記は、桁数の違いはあるけれど、次のどれかだと思う。。
- Ver.1.2 (ゼロ詰めなし)
- Ver.1.02 (ゼロ詰めあり、2桁)
- Ver.1.002(ゼロ詰めあり、3桁)
Windowsや.NET Framework、Linux、Macなどは、ゼロ詰めなしで、、PS3のシステムバージョンやフリーソフトの一部はゼロ詰めありという感じになっている。(ちょっと思いついたところだけ調べただけなので、まだまだ調べたりないけれど)。で、自分はどのバージョン表記にならえばいいんだろうか、というのが今日のアジェンダ。
会社では、「1.02」というようなゼロ詰め2桁表記を使うことが多い。けれど、今回は .NET アプリなんですよ。.NETでは通常、4桁ゼロ詰めなしの表記を使っているようですし、Windowsのファイルエクスプローラでプロパティを見たときも、たいてい4桁ゼロ詰めなしですし、詳細表示にしても同様です。そんなわけで、.NET アプリのバージョンを付けるときは、4桁ゼロ詰めなし表記にしたいんですけど・・・・。
個人的には、会社の方針云々を使ってもらう人に押しつけるよりも、郷に入っては郷に従うのでいいんじゃないかと思うんですけど・・・・・・・。(それに、はじめから用意されている方法・指針で付けた方が楽ですし)。
※AssemblyVersionとAssemblyFileVersionとAssemblyInformationalVersionって、何か明確に区別するのが良いんでしょうか。何かご存じの方いれば、よろしくお願いします。
2008年5月13日
#
あぁ、学生に戻りたい。
http://www.microsoft.com/japan/presspass/detail.aspx?newsid=3437
2008年5月8日
#
シェーカーソート(シェーカーソート、Shaker sort、カクテルソート、Cocktail sort、双方向バブルソート、bidirectional bubble sort)。
バブルソートの改良版。バブルソートで1回のループで昇順と降順を一度に並び替える。同じ要素の並びは変わらない安定ソート。
template <typename TElement, typename TSize>
void ShakerSort(TElement * data, const TSize size)
{
TSize head = 0;
TSize tail = size - 1;
while (head < tail)
{
TSize swapPos = head;
for (TSize i = head; i < tail; ++i)
{
TElement diff = data[i] - data[i+1];
if (diff > 0)
{
data[i ] = data[i+1];
data[i+1] = diff + data[i];
swapPos = i;
}
}
tail = swapPos;
for (TSize i = tail; i > head; --i)
{
TElement diff = data[i] - data[i+1];
if (diff > 0)
{
data[i ] = data[i+1];
data[i+1] = diff + data[i];
swapPos = i;
}
}
{ // TSizeがunsigned型の場合、対策。
TSize i = head;
TElement diff = data[i] - data[i+1];
if (diff > 0)
{
data[i ] = data[i+1];
data[i+1] = diff + data[i];
swapPos = i;
}
}
head = swapPos;
}
}
ハトの巣ソート(ピジョンソート、Pigeon sort)。
いまいち理解できていないので、Wikipedia様に丸投げ→→「Pigeonhole sort」。( 18:06, 19 March 2008版には擬似コードもあり。)
メモリは食うけど、ソートは馬鹿早い。同じ要素の並びは変わらない安定ソート。
追記@2008-05-12T23:39+09:00:新しいバージョンをアップ。
/* データはユニークである必要があります。 */
template<typename TElement, typename TSize>
void PigeonholeSort(TElement * data, const TSize size)
{
TElement min = data[0];
TElement max = min;
for (TSize i = 1; i < size; ++i) {
min = data[i] < min ? data[i] : min;
max = data[i] > max ? data[i] : max;
}
TSize range = max - min + 1;
TElement * pigeonholes = new TElement[range];
for (TSize i = 0; i < range; ++i)
pigeonholes[i] = 0; /* memsetで十分。 */
for (TSize i = 0; i < size; ++i)
pigeonholes[data[i]-min] = data[i];
TSize dataPos = 0;
for (TSize i = 0; i < range; ++i)
if (pigeonholes[i] != 0)
data[dataPos++] = i + min;
delete[] pigeonholes;
}
追記@2008-05-08T17:19+09:00:下記のコードはちょっと間違えています。そのうち修正しますので、くれぐれも参考にしないよう、お願いします。
#include <map>
template<typename TElement, typename TSize>
void PigeonholeSort(TElement * data, const TSize size)
{
typedef std::map<TElement, std::vector<TElement> > TMap;
TMap pigeonholes;
for (TSize i = 0; i < size; ++i)
pigeonholes[data[i]].push_back(data[i]);
TSize dataPos = 0;
const TMap::const_iterator end = pigeonholes.end();
for (TMap::iterator it = pigeonholes.begin(); it != end; ++it)
{
const TMap::value_type & pigeonhole = *it;
const TSize size = pigeonhole.second.size();
for (TSize i = 0; i < size; ++i)
{
data[dataPos++] = pigeonhole.first;
}
}
}
選択ソート(直接選択ソート、Selection sort)。
一番小さいのを選んで、先頭へ。次に小さいのを選んで2番目に・・・と並べる。一般的には、同じ要素の並びが変わってしまう不安定ソート。
template<typename TElement, typename TSize>
void SelectionSort(TElement * data, const TSize size)
{
TSize tail = size - 1;
for (TSize head = 0; head < tail; ++head)
{
TElement * pMin = (data + head);
for (TSize pos = head + 1; pos < size; ++pos)
if (data[pos] < *pMin) pMin = (data + pos);
if (data + head != pMin)
{
TElement temp = data[head];
data[head] = *pMin;
*pMin = temp;
}
}
}
2008年5月7日
#
バブルソート(Bubble sort)
2つの要素を比べては交換、比べては交換して、交換できる要素がなくなれば終了。同じ要素の並びは変わらない安定ソート。
template <typename TElement, typename TSize>
void BubbleSort(TElement * data, const TSize size)
{
bool swapped = false;
do
{
swapped = false;
const TSize max = size - 1;
for (TSize i = 0; i < max; ++i)
{
TElement diff = data[i] - data[i+1];
if (diff > 0)
{
data[i ] = data[i+1];
data[i+1] = diff + data[i];
swapped = true;
}
}
} while (swapped);
}
これでOK?
交換するコードが、味噌味。