お願いします。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
入門者以下

お願いします。

#1

投稿記事 by 入門者以下 » 15年前

ソフトやったことないのですが、
会社からソース解析の指示を受けました。
まったく手がつけられず困っています。
お助けください。

以下

CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol)
{
ASSERT(!GetVirtualMode());

if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
{
ASSERT( FALSE);
return NULL;
}
CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject();
if (!pCell)
return NULL;

pCell->SetGrid(this);
pCell->SetCoords(nRow, nCol);

if (nCol < m_nFixedCols)
pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL);
if (nRow < m_nFixedRows)
pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW);

pCell->SetFormat(pCell->GetDefaultCell()->GetFormat());

return pCell;
}

以上

どのような操作?がされているのでしょうか?
ご教示ください。

Poco

Re:お願いします。

#2

投稿記事 by Poco » 15年前

新規にグリッドのセルを生成して、必要な初期化を行っているだけです。

たかぎ

Re:お願いします。

#3

投稿記事 by たかぎ » 15年前

CodeProjectあたりで出回っているCGridCtrlのソースかと思いますが、それであっていますか?
そうでないなら、開発環境を明示してください。

入門者以下

Re:お願いします。

#4

投稿記事 by 入門者以下 » 15年前

ぽこ様、高木様
ご回答ありがとうございます。

ぽこ様のおっしゃる通りネット上に落ちているCGridCtrlのソースです。
質問ではなく、依頼のようになってしまい申し訳ありません。。。
手のつけようがなくて。


開発環境
Visual Studio2008、XPです。

たかぎ

Re:お願いします。

#5

投稿記事 by たかぎ » 15年前

C++やMFCはどの程度まで理解できていますか?
概要としては、ぽこさんが書かれているとおりですが、そのレベルでよいのでしょうか?

入門者以下

Re:お願いします。

#6

投稿記事 by 入門者以下 » 15年前

もともとハードで今年からソフト屋?になり、
お恥ずかしながらほとんど理解できていません。。
MFCについては、開発するために便利な様々な機能、クラスみたい認識でいます。
ソースについては、調べ調べで変数、引数、関数、*がどのような物かくらいです。
できれば1行ずつコメントを入れていただけるとありがたいのですが・・・
私の理解では下記のレベルになってしまいます。


CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol) //引数int型のnRowとnCol
{
ASSERT(!GetVirtualMode()); //ASSERTで!GetVirtualMode()の評価を行う

if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase))) //解読不能
{
ASSERT( FALSE);
return NULL; //NULLを返す
}
CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject(); //ポイントpCell
if (!pCell) //もし(!pCell)のときNULLを返す
return NULL;

pCell->SetGrid(this); //理解できない、グリッド作成??
pCell->SetCoords(nRow, nCol); //理解できない

if (nCol < m_nFixedCols) //nColよりm_nFixedColsが多きとき下記を実行
pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL); //理解できない
if (nRow < m_nFixedRows) //nRowよりm_nFixedColsが多きとき下記を実行

pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW); //理解できない

pCell->SetFormat(pCell->GetDefaultCell()->GetFormat()); //表示書式を設定?

return pCell; //pCellを返す。pCellの中身は?
}

一つ一つの単語?は調べながらでわかるのですが、つながるとどのような処理になるのかわかりません。
この程度しか理解していないのにお付き合いいただき有難うございます。

sizuma

Re:お願いします。

#7

投稿記事 by sizuma » 15年前

C++は文法書を読んだくらいで、MFCはさわったこともありませんので、僕の勉強で書いてみました。
参考になるかは分かりませんが、間違えはきっと他のプログラマさまが訂正してくれるはず・・・・
プログラミング1年目ぐらいですので、そんくらいの人のコメントだと思ってみてください^^;
CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol) //引数int型のnRowとnCol
{ 
    ASSERT(!GetVirtualMode()); //ASSERTで!GetVirtualMode()の評価を行う

    //m_pRtcDefaultが生成してあり、かつCGridCellBaseを実行可能な派生クラスであるか調べてる?
    if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase))) //解読不能
    { 
        ASSERT( FALSE); 
        return NULL; //NULLを返す
    } 
    //ファクトリメソッドでインスタンスを生成し、CGridCellBase*型に明示的にキャストする
    CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject(); //pCellへのポインタ
    if (!pCell) //もし(!pCell)のときNULLを返す
        return NULL; 

    pCell->SetGrid(this); //pCellのグリッドとして作成したインスタンスを登録
                          //つまり、呼び出す時に使ったインスタンスを登録。
    pCell->SetCoords(nRow, nCol);  //指定した列、行を登録

    //pCellのStateフィールドに状態を表すビット列があり、そこのビットをオンにする
    if (nCol < m_nFixedCols) //nColがm_nFixedColより小さければ下記
        pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL); 
    if (nRow < m_nFixedRows) //同じく、上限より小さければ
        pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW); 
    //pCellのフォーマットに、CGridCellクラスのデフォルトフォーマットをセットする 
    pCell->SetFormat(pCell->GetDefaultCell()->GetFormat()); //表示書式を設定?

    //pCellはポインタ(ポインタの先に中身がある)
    return pCell; //pCellを返す。pCellの中身は?
}
コメント中にも書いてますが、pCellはこのメソッド(関数)で作ったグリッドを指すポインタです。
グリッドのアドレス(住所のようなもの)でこれを返せば、グリッドの中身もその住所の場所なので分かりますよね。
ちなみに、グリッド自体を現すには
*pCellとすることで、住所の先にあるグリッドを意味します。

お仕事大変ですね^^:
ソフトしか作ったことがない人に電子回路図の説明を書けって言われるようなものでしょうか。
(組込みしてたら分かるんでしょうけど)

関係ないですが、nullってキャストして返してもいいのかな・・・
代入するときは全然意識しなかったけど、returnするのはキャストして書きたくなります 画像

Poco

Re:お願いします。

#8

投稿記事 by Poco » 15年前

私がソースコードの解析を依頼された場合、
全体を俯瞰し、概要をつかむことから始めます。

闇雲に一行ずつ読み解くことは「絶対に」行いません。
もし入門者以下さんの頭の中に、このソースに対する、
ハードウェアでいうところブロック図が無い場合は、
それを構築することから始めるべきです。

まず、該当する関数につけられているコメントを読みます。
コメントは、*.cppファイルか*.hファイルにあるはずです。
たかぎさんは突っ込みませんでしたが、私の最初の回答は
このソースにあったコメントを日本語に訳しただけです。

全体の概要を把握する前ならこれで十分だと考え、
別の場所の解析を行います。

クドいようですが、全体の概要把握が優先されるべきことです。

さて本題。

引用が前後しますが、

> 一つ一つの単語?は調べながらでわかるのですが、つながるとどのような処理になるのかわかりません。

これに対する回答は、関数の先頭にあるコメントのまんまです。

以降、入門者以下さんの疑問に、「推測」で答えさせていただきます。
ソースコードをパッと見たときの私の所感です。

> CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol) //引数int型のnRowとnCol
このグリッドは何行何列目って指定して、セルを作るんだな。

> ASSERT(!GetVirtualMode()); //ASSERTで!GetVirtualMode()の評価を行う
バーチャルモードとかいうモードがあって、このモードの時はセルの作成は出来ないんだな。

> if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase))) //解読不能
> {
> ASSERT( FALSE);
> return NULL; //NULLを返す
> }
メンバm_pRtcDefaultがNULLだったり、CGridCellBaseの派生クラスでない場合は生成出来ないんだな。

> CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject(); //ポイントpCell
> if (!pCell) //もし(!pCell)のときNULLを返す
> return NULL;
ここで、セルを生成しているな。これ以降が、セルの初期設定だな。

> pCell->SetGrid(this); //理解できない、グリッド作成??
セルの初期設定には、自分を生成したグリッドを記録する必要があるんだな。
(セル自身に所属するグリッドを記録する必要があるんだな)

> pCell->SetCoords(nRow, nCol); //理解できない
Coordって座標って意味だろうから、セル自身に自分が何行何列目のセルか記録する
必要があるんだな。

> if (nCol < m_nFixedCols) //nColよりm_nFixedColsが多きとき下記を実行
> pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL); //理解できない
> if (nRow < m_nFixedRows) //nRowよりm_nFixedColsが多きとき下記を実行
> pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW); //理解できない
きっとグリッドに「行の固定」や「列の固定」って機能があって、1列目からm_nFixedCols列目までが
固定されるんだろうな(同様に1行目からm_nFixedRows行目も固定されるんだな)。
だからセルがその範囲に入っていた場合は、セルの状態に「固定されてますビット」を立てるんだろうな。

> pCell->SetFormat(pCell->GetDefaultCell()->GetFormat()); //表示書式を設定?
表示形式はデフォルトの設定を使うんだな。

ソースコードの解析はジグソーパズルと同じで、最初は何をやっているのか、さっぱり分かりません。
いろんな箇所を目を通していく(目を通すだけ、深入りはダメ)に連れて、徐々により細かい部分が理解
できるようになります。

私なら、上記のような推測を行った後、この関数を離れ、
変数m_pRtcDefaultかm_nFixedColsを追います。

なんかグダグダになっちゃいましたが、以上が私なりの回答です。

たかぎ

Re:お願いします。

#9

投稿記事 by たかぎ » 15年前

まずはじめに、CGridCtrlというのが何をするものか理解できていますか?
それが分からないと先に進みません。

結論をいえば、エクセルのような格子状の表を作るためのクラスです。
rowは格子の行、すなわち縦の位置であり、column(略してcol)は格子の列、すなわち横の位置にあたります。
cellは、格子の個々のマスのことです。
gridというのはこの格子のことです。

CGridCtrlでは、各cellをいろいろな形にカスタマイズできるようになっています。
具体的には、基本的には各cellはテキストを表示・編集できるだけですが、カスタマイズすることでコンボボックスにしたり、画像を表示したりできるようになります。
CGridCellBaseは、そのようにカスタマイズされたcellに共通のインタフェースを与えるための基底クラスです。

クラスについてはわかるでしょうか?
ハード屋さんにもわかりやすいようにLSIに例えると、クラスはLSIの仕様のようなものです。個々の仕様ごとに型番(クラス名: 例えばCGridCellBaseなど)が付いています。そして、その型番の個々のLSI(現物)に該当するものがオブジェクト(インスタンスと呼ぶこともある)になります。
クラスは継承することができますが、これは例えていえば、ピンコンパチのLSIを作るようなものです。

ぽこさんがいわれているように、全体を俯瞰することは重要で、難しいようであれば、Doxygen(http://www.doxgen.jp/)などを使って視覚化してみるのもよいでしょう。

今ちょっと時間がないので、夕方以降であればもう少し詳しい説明ができるかと思います。

バグ

Re:お願いします。

#10

投稿記事 by バグ » 15年前

ぽこさんの例えが上手だなぁ…と感心しつつ眺めてます。

私も以前、ハードの事が全く分からないのにVHDLでFPGAの回路を組んだ事があります。

その時は専門書を読みながら、『これはC++でいうクラスみたいなものだな…』、『これは派生クラスっぽい?いや、内包してるだけかな?』…みたいな感じで自分の得意分野に置き換えながら進めていきました。

MFCは便利なようで、仕組みというか構成を理解するまでは、取っ付きづらいかと思いますが頑張ってください。

入門者以下

Re:お願いします。

#11

投稿記事 by 入門者以下 » 15年前

sizuma様、ぽこ様、たかぎ様、バグ様

ご回答ありがとうございます。
別件のiniファイル読み込みボタンの実装?に手間取ってしましました。。。
返信が遅くなってしまい申し訳ありません。


sizuma様
大変参考になりました。
これを参考にして解析進めて行きたいと思います。

ぽこ様
ハードに置き換えての説明、わかりやすくとても勉強になりました。
全体の概要の重要性がよくわかりました。
上記のソースだけでなく全体に目を向けて行きたいと思います。
また1行ずつのコメントまでして頂きありがとうございます。

たかぎ様
CGridCtrlについてですが、ざっくりとExcelの表のようなものとの認識でいましたが、
おかげでより一層CGridCtrlについて理解できました。
たかぎ様の説明を見て、より深くCGridCtrlについて理解できました。
クラス=集積回路、クラス、継承についてのイメージが凄い湧きました。
わざわざハード用語に置き換えて説明して頂き、ありがとうございます。
お時間がある時でいいのでご教示お願い致します。

バグ様
ハードの事が全く分からないのに回路を組んだなんて凄いですね!
ありがとうございます。
少しずつソフトについて理解できるよう頑張って行きたいと思います。

皆様
こんなにたくさんの方からの回答、本当にありがとうございます。
丁寧に説明もしてくださって感無量です。

たかぎ

Re:お願いします。

#12

投稿記事 by たかぎ » 15年前

http://repo.isis.vanderbilt.edu/doxygen ... de8195ed59
↑このあたりを見れば、多少は解釈しやすくなるかもしれません。
まあ、あまりよい資料ではないので、気休め程度かもしれませんが...

一応私もコメントを付けておきます。

// CGridCtrlのメンバ関数CreateCellの定義
//   メンバ関数CreateCellは、行と列をパラメータとして受け取り、生成したセルを返す
> CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol)
> {

// この部分は状態の判定(要はエラーチェック)
> ASSERT(!GetVirtualMode());
>
> if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
> {
> ASSERT( FALSE);
> return NULL;
> }
> CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject();
> if (!pCell)
> return NULL;

// 生成したセルが、どのグリッドのどの位置に配置されるかを設定
> pCell->SetGrid(this);
> pCell->SetCoords(nRow, nCol);

// 各種属性を設定
> if (nCol < m_nFixedCols)
> pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL);
> if (nRow < m_nFixedRows)
> pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW);

// Format(具体的に何を意味するかは忘れました)をデフォルトに設定
> pCell->SetFormat(pCell->GetDefaultCell()->GetFormat());

// 生成したセルを返す
> return pCell;
> }

まあ、こんな感じです。

入門者以下

Re:お願いします。

#13

投稿記事 by 入門者以下 » 15年前

たかぎ様
コメントにURLありがとうございます。
参考にさせていただきます。
また、勝手に拝見させて頂いたのですが、
http://www.kijineko.co.jp/の方も、今後に役立てて行きたいと思います。

本当にありがとうございました。

kazuoni

Re:お願いします。

#14

投稿記事 by kazuoni » 15年前

> http://www.kijineko.co.jp/の方も、今後に役立てて行きたいと思います。

たかぎさんや、その社員さん(?)が書いているコラムって
評判いいですよねw
以前は「コラムはしょせんコラム程度に」っと書かれていらしたかと思いますが・・・。

たかぎ

Re:お願いします。

#15

投稿記事 by たかぎ » 15年前

> 以前は「コラムはしょせんコラム程度に」っと書かれていらしたかと思いますが・・・。

どんな文脈でそういったのか、ぜんぜん覚えていませんが、まあ役に立ててくれる人がいるのはよいことです。
うちのサイトは、原則として初心者に迎合しない主義で運営しています。
ですので、コメントやメールでの質問を随時受け付けています。

商用サイトとしては不親切なので、できれば初心者向けの(あくまでビジネス用の)サイトを別途作った方がよいのですが、そこまで手が廻っていません。

入門者以下

Re:お願いします。

#16

投稿記事 by 入門者以下 » 15年前

たかぎ様
>コメントやメールでの質問を随時受け付けています。

心強くありがたいお言葉ありがとうございます。
今後、自分で調べてもわからない事がありましたら
質問させて頂きます。
その時は、よろしくお願い致します。

閉鎖

“C言語何でも質問掲示板” へ戻る