HIRASE CONNECTION WK

programming collection

目次

Blog 利用状況

ニュース

あわせて読みたいブログパーツ

書庫

日記カテゴリ

Link Collection

2008年7月2日 #

[C#] SplitContainer/SplitterPanel 使いにくい!

つぶやき、ですが・・・

.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 を閉じて欲しいのよね(そうじゃないときは、例外発生か、閉じられないか)。

以上

posted @ 1:20 | Feedback (0)

2008年6月10日 #

[C++/CLI] RootNamespaceが狂っていると、System.Resources.MissingManifestResourceExceptionが発生します。

C++/CLIアプリを作成して、ローカライズ(L10N or I18N) します。このとき、もし自分で名前空間を変えているなら、実行時に「System.Resources.MissingManifestResourceException」例外が発生します。

詳細

どうもアセンブリリソースを埋め込む際に、ルート名前空間を見て名前を修飾して埋めているらしく、ローカライズしたフォーム(ApplyResourceを呼びだしている)クラスの名前空間がルート名前空間とずれていると、実行時に適切なリソースを見つけられなくて、「System.Resources.MissingManifestResourceException」例外が発生するようです。

対処方法は2つ。(ま、結局2つともに同じことなんですけど)

  1. フォームクラスの名前空間を、ルート名前空間に合わせる。
  2. ルート名前空間を、フォームクラスの名前空間に合わせる。

ルート名前空間は、プロジェクトのプロパティウィンドウ(プロパティページでもプロパティマネージャでもないですよ!)の、ルート名前空間で変更するか、プロジェクトをいったんソリューションエクスプローラからアンロードして、右クリックで編集するなどします。

あぁ、つらい。

posted @ 15:07 | Feedback (0)

2008年6月9日 #

[C++/CLI] アンマネージのコールバックにマネージのメソッドを登録する。

こんな方法は・・・・・・・

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

posted @ 21:34 | Feedback (2)

2008年5月27日 #

[C] wchar_tって・・・。

VC2008で、ソースファイルのプロパティで
「詳細」の「コンパイル言語の選択」を「Cコードとしてコンパイル (/TC)」として、
「言語」の「wchar_t をビルトイン型として扱う (/Zc:wchar_t」を「はい」にすると、
wchar_t が組み込み型として使えそうなのに、使えないんですね・・・。

# wchar.hをincludeすれば使えますけど、unsigned short扱いだし、
# CRTを使いたくないのに、wchar.h から crtdefs.h を読み込んじゃうし・・・


C で書くなと??

posted @ 22:37 | Feedback (5)

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って、何か明確に区別するのが良いんでしょうか。何かご存じの方いれば、よろしくお願いします。

posted @ 21:05 | Feedback (5)

2008年5月13日 #

Microsoft DreamSpark はじめました。

あぁ、学生に戻りたい。 http://www.microsoft.com/japan/presspass/detail.aspx?newsid=3437

posted @ 23:15 | Feedback (2)

2008年5月8日 #

[C++] シェーカーソート

シェーカーソート(シェーカーソート、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;
    }
}

posted @ 2:33 | Feedback (0)

[C++] ハトの巣ソート

ハトの巣ソート(ピジョンソート、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;
        }
    }
}

posted @ 1:37 | Feedback (5)

[C++] 選択ソート

選択ソート(直接選択ソート、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;
        }
    }
}

posted @ 0:18 | Feedback (0)

2008年5月7日 #

[C++] バブルソート

バブルソート(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?

交換するコードが、味噌味。

posted @ 23:34 | Feedback (0)