質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.40%

  • C

    4117questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3949questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Visual Studio

    2095questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

ビットマップ形式での描画(月)の上から普通の図形(星)の描画をしたいができない

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 266

TRON1216.

score 23

ビットマップ形式でペイントしたお月様の背景に星を描画したいと考えています。月を描画せずに星だけ描画することはできるのですが、ビットマップ形式で月とその背景の宇宙空間を描画し、その上から星を描画しようとすると、月と宇宙空間は正しく描画されますが星が描画されません。星は座標データを読み込みSetPixel関数を用いて十字架の形で描画させています。ビットマップ形式での描画とただの図形(星)の描画を同じウィンドウで行うには何か書き方のポイントとかがあるのでしょうか?(星を描画する関数の呼び出すタイミングがおかしいとか)何かアドバイスがあればよろしくお願い致します。

//様々な作業の中心となるダイアログ
BOOL CALLBACK MyDlgProc( HWND hDlg, UINT msg, WPARAM wp, LPARAM lp )
{
    char    *fname;        // ファイル名
    static FILE *fp;    // FILEへのポインタ
    static FILE *fp1;

    int year, month, day, hour, min, sec;    //ETを秒で求めたい年, 月, 日, 時, 分, 秒(UTC)

    int i;
    double Time;
    double Time_now;
    double dt;
    double theta;
    double RA, DEC; //赤経、赤
    double koukei, koui; //黄経、黄緯

    switch(msg){
        case WM_INITDIALOG:

            //2019年12月26日12時0分0秒(UTC)に初期設定する。
            SetDlgItemInt(hDlg, IDC_EDIT_Y, 2019, FALSE);
            SetDlgItemInt(hDlg, IDC_EDIT_M, 12, FALSE);
            SetDlgItemInt(hDlg, IDC_EDIT_D, 26, FALSE);
            SetDlgItemInt(hDlg, IDC_EDIT_H, 12, FALSE);
            SetDlgItemInt(hDlg, IDC_EDIT_MIN, 0, FALSE);
            SetDlgItemInt(hDlg, IDC_EDIT_S, 0, FALSE);

            CheckDlgButton( hDlg, IDC_CHECK_DISPLAY1, BST_UNCHECKED);

            return TRUE;

        case WM_COMMAND:
            switch(LOWORD(wp)){
                case IDC_BUTTON_OPEN1:    // CH1のファイルを開く処理
                    if( fname = filename() ){
                        if ( fp ) fclose ( fp );
                        fopen_s ( &fp, fname, "r" );
                        //read_data(hDlg, fp, 1);
                    //    MessageBox(NULL ,"座標ファイル読み込み成功", "CH1", MB_OK);// ファイルをテキスト読み込みモードで開く



                        if (fname = filename()) {
                            if (fp1) fclose(fp1);
                            fopen_s(&fp1, fname, "r");
                            read_star(hDlg, fp1, 1);
                            //MessageBox(NULL, "星のデータ読み込み成功", "CH1", MB_OK);
                            fclose(fp1);
                        }

                        if (read_data(hDlg, fp, 1))             // CH1で読み込む
                            CheckDlgButton(hDlg, IDC_CHECK_DISPLAY1, BST_CHECKED);// チェックボタンを「表示」とする

                        fclose( fp );
                        InvalidateRect(hWnd, NULL, TRUE);
                    }


                    return TRUE;

                case ID_OK://OKボタンが押された
                    //MessageBox(NULL ,"座標ファイル読み込み成功", "CH1", MB_OK);
                    //Time =  et(year, month, day, hour, min, sec)/*GetDlgItemInt(hDlg, IDC_EDIT_ET, NULL, FALSE)*/;

                    year = GetDlgItemInt(hDlg, IDC_EDIT_Y, NULL, FALSE);    //エディットボックスから年を読み込む
                    month = GetDlgItemInt(hDlg, IDC_EDIT_M, NULL, FALSE);    //以下同様
                    day = GetDlgItemInt(hDlg, IDC_EDIT_D, NULL, FALSE);
                    hour = GetDlgItemInt(hDlg, IDC_EDIT_H, NULL, FALSE);
                    min = GetDlgItemInt(hDlg, IDC_EDIT_MIN, NULL, FALSE);
                    sec = GetDlgItemInt(hDlg, IDC_EDIT_S, NULL, FALSE);

                    //関数etに上記を引数として渡すと、秒で表されたElapsed Timeが戻される。
                    Time =  et(year, month, day, hour, min, sec);

                    for(i=0; i<=total_n; i++){
                        if(rh[i].ET > Time){
                            g = i-1;
                            dt = Time - rh[g].ET;
                            //sprintf_s(szBuf, 256, "%d", g);
                            //MessageBox(NULL, szBuf, "超える直前のデータの番号", MB_OK);
                            break;
                        }

                    }

                    //sprintf_s(szBuf, 256, "%d %lf",g , dt);
                    //MessageBox(NULL, szBuf, "データ", MB_OK);

                    //sprintf_s(szBuf, 256, "%lf", haET);
                    //MessageBox(NULL, szBuf, "元データ", MB_OK);



                    eql.x = rh[g].VXEQL * dt + rh[g].XEQL;
                    eql.y = rh[g].VYEQL * dt + rh[g].YEQL;
                    eql.z = rh[g].VZEQL * dt + rh[g].ZEQL;

                    moon.x = rh[g].VXMOON * dt + rh[g].XMOON;
                    moon.y = rh[g].VYMOON * dt + rh[g].YMOON;
                    moon.z = rh[g].VZMOON * dt + rh[g].ZMOON;

                    sun.x = rh[g].VXSUN * dt + rh[g].XSUN;
                    sun.y = rh[g].VYSUN * dt + rh[g].YSUN;
                    sun.z = rh[g].VZSUN * dt + rh[g].ZSUN;

                    earth.x = 0;
                    earth.y = 0;
                    earth.z = 0;

                    //sprintf_s(szBuf, 256, "%lf %lf %lf %lf %lf %lf", eql.x , eql.y, eql.z, moon.x, moon.y, moon.z);
                    //MessageBox(NULL, szBuf, "eql.x, moon.x", MB_OK);

                    EQL_MOON = sqrtf((moon.x - eql.x)*(moon.x - eql.x) + (moon.y - eql.y)*(moon.y - eql.y) + (moon.z - eql.z)*(moon.z - eql.z));
                    SUN_MOON = sqrtf(sun.x * sun.x + sun.y * sun.y + sun.z * sun.z);
                    EARTH_MOON = sqrtf(moon.x * moon.x + moon.y * moon.y + moon.z * moon.z);

                    //t = 360*3474/(2*M_PI*EQL_MOON);//視直径を計算
                    s = (3474.0*0.00005) / EQL_MOON; //月の相対的な大きさを計算

                    //sprintf_s(szBuf, 256, "%lf %lf", EQL_MOON, s);
                    //MessageBox(NULL, szBuf, "EQL_MOON, s", MB_OK);

                    for(i=0; i<=total_n2; i++){
                     RA = 2*M_PI*(h[i].RA_h + h[i].RA_m/60 + h[i].RA_s/3600)/24; //単位を時で統一
                     DEC = 2*M_PI*(h[i].Dec_d + h[i].Dec_m/60 + h[i].Dec_s/3600)/360; //単位を度で統一
                       if (h[i].Dec_sig == FALSE) {
                          DEC = -DEC;
                       }
                     koukei = atan2(sin(M_PI*23.43 / 180)*sin(DEC)+cos(M_PI*23.43 / 180)*cos(DEC)*sin(RA),cos(DEC)*cos(RA)); //単位はrad
                       if (koukei < 0) {
                          koukei = koukei + 2 * M_PI; //単位はrad
                       }
                     koui = asin(cos(M_PI*23.43 / 180)*sin(DEC) - sin(M_PI*23.43 / 180)*cos(DEC)*sin(RA));

                     star[i].x = cos(koui)*cos(koukei);
                     star[i].y = cos(koui)*sin(koukei);
                     star[i].z = sin(koui);
                    }


                    //座標変換1
                    eql = Cordi_Trans1(eql, moon);
                    moon = Cordi_Trans1(moon, moon);
                    sun = Cordi_Trans1(sun, moon);
                    earth = Cordi_Trans1(earth, moon);


                    //座標変換2
                    theta = atan2(eql.y, eql.x);
                    eql = Cordi_Trans2(eql, theta);
                    sun = Cordi_Trans2(sun, theta);
                    earth = Cordi_Trans2(eql, theta);
                    for(i=0; i<=total_n2; i++){
                        star[i] = Cordi_Trans2(star[i], theta);
                    }

                    //座標変換3
                    theta = atan2(eql.x, eql.z);
                    eql = Cordi_Trans3(eql,theta);
                    sun = Cordi_Trans3(sun,theta);
                    earth = Cordi_Trans3(earth,theta);
                    for(i=0; i<=total_n2; i++){
                        star[i] = Cordi_Trans3(star[i], theta);
                    }

                    //座標変換4
                    theta = atan2(-sun.x, sun.y);
                    eql = Cordi_Trans2(eql,theta);
                    sun = Cordi_Trans2(sun,theta);
                    earth = Cordi_Trans2(earth,theta);
                    for(i=0; i<=total_n2; i++){
                        star[i] = Cordi_Trans2(star[i], theta);
                        if(star[i].z < 0){
                            star[i].x = star[i].x * (-50 / star[i].z);
                            star[i].y = star[i].y * (-50 / star[i].z);

                           star[i].x = (star[i].x) / 2 * (988.5 / 10);
                           star[i].y = (star[i].y) / 2 * (741 / 10);
                       }
                    }

                    if(sun.y > 0){
                      theta = atan2(-sun.x, sun.y) + M_PI;
                      eql = Cordi_Trans2(eql,theta);
                      sun = Cordi_Trans2(sun,theta);
                      earth = Cordi_Trans2(earth,theta);
                     for(i=0; i<=total_n2; i++){
                        star[i] = Cordi_Trans2(star[i], theta);
                        if(star[i].z < 0){
                            star[i].x = star[i].x * (-50 / star[i].z);
                            star[i].y = star[i].y * (-50 / star[i].z);

                           star[i].x = (star[i].x) / 2 * (988.5 / 10);
                           star[i].y = (star[i].y) / 2 * (741 / 10);
                       }
                    }
                    }


                    //sprintf_s(szBuf, 256, "%lf %lf", star[5].x, star[5].y);
                    //MessageBox(NULL, szBuf, "変換後データ", MB_OK);


                    //g = GetDlgItemInt( hDlg, IDC_EDIT_header2, &number, FALSE );
                    InvalidateRect(hWnd_bitmap, NULL, TRUE);
                    return TRUE;
                
                
                case IDCANCEL:                //右上の×クリックで終了
                    PostQuitMessage(0);
                    DestroyWindow (hWnd);
                    
                    DestroyWindow (hDlg);
                    return TRUE;

                        }
            return TRUE;

    }
    return FALSE;
}

   図1:月と星を同時に描画した時   イメージ説明   図2:星だけ描画した時   イメージ説明      star[i].x += (rect.right - rect.left) / 2;   star[i].y += (rect.bottom - rect.top) / 2;   と書き換えると   ![イメージ説明](46849720638852e605c4c7f37f3cfe60.png)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ppn

    2018/10/21 19:48

    コードを見ていないので憶測ですが、星は星の部分だけが白で描画されるのですよね。にもかかわらず、月が消え、背景がグレーになっているということは、全体を上書きしてしまっているのでは?と思いました。

    キャンセル

  • TRON1216.

    2018/10/23 23:59

    そうです。星だけが白で描画されます。全体を上書きしているというコードの箇所を見つければ良い可能性があるということでしょうか?

    キャンセル

  • ppn

    2018/10/24 00:45

    ですです。おそらくは…ですが。

    キャンセル

回答 2

0

提示されているソースだけで実行することはできないので、完全な再現は不可能でした。

私が適当に動かした感じだと disp_star_xy の以下の部分で広域変数 star の座標が恒久的に変化するため、ありえない位置で星が描画されている感じですね。

            star[i].x = star[i].x - (rect.right-rect.left)/2;
            star[i].y = (rect.bottom - rect.top) / 2 - star[i].y;


InvalidateRect を 2 回以上呼び出すと X 座標がマイナスとなって描画位置がウィンドウの範囲に入らずに消えています。該当関数を呼び出すかどうかでそのような差になっているのではないでしょうか?


2018/10/24 追記
すみません。最初に伝えるのを忘れてましたが、描画処理に関しては提示されている元のコードで問題なく星は描画できています。
サンプル画像
コード的に変えたのは月の描画部分はめんどくさいのでカットしています。星は移動しないように disp_star_xy 関数の座標更新部分を変更してあります。単色の星だと寂しいので、色が着くようにしてみました。それ以外の部分は提示されているコードのままです。これで問題がある場合、さらに提示されていない部分を提示していただければ、回答しやすいかと思います。

#include <windows.h>
#include <math.h>

#define MAX_LOADSTRING 100
#define ID_MYTIMER      33
#define MAX_STAR       520

typedef struct {
    HINSTANCE hInst_bitmap;
    HWND hWnd_bitmap;
    BYTE *lpBmpData;
    BITMAPINFO bmi;
    RGBQUAD dummy[3];
    char *fname;
    int fsize;
} IMG;

struct STAR : public POINT {
    double Mag;
};

// グローバル変数:
HINSTANCE hInst;
WCHAR szTitle[] = L"teratail153158";
WCHAR szWindowClass[] = L"teratail153158";
STAR star[MAX_STAR];

// このコード モジュールに含まれる関数の宣言を転送します:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL disp_star_xy(HDC hdc, RECT rect);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    for (int i = 0; i < MAX_STAR; i++) {
        star[i].x = 988 * rand() / RAND_MAX;
        star[i].y = 741 * rand() / RAND_MAX;
        star[i].Mag = 1.0 - 4.0 * rand() / RAND_MAX;
    }

    // グローバル文字列を初期化する
    MyRegisterClass(hInstance);

    // アプリケーション初期化の実行:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    MSG msg;

    // メイン メッセージ ループ:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}



//
//  関数: MyRegisterClass()
//
//  目的: ウィンドウ クラスを登録します。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_3DSHADOW);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = NULL;

    return RegisterClassExW(&wcex);
}

//
//   関数: InitInstance(HINSTANCE, int)
//
//   目的: インスタンス ハンドルを保存して、メイン ウィンドウを作成します
//
//   コメント:
//
//        この関数で、グローバル変数でインスタンス ハンドルを保存し、
//        メイン プログラム ウィンドウを作成および表示します。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // グローバル変数にインスタンス ハンドルを格納する

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: メイン ウィンドウのメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウを描画する
//  WM_DESTROY  - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd_bitmap, UINT msg, WPARAM wp, LPARAM lp)
{
    IMG g_img;
    g_img.lpBmpData = NULL;
    PAINTSTRUCT ps;
    HDC hdc, hdc_mem;
    HBITMAP hBmp;
    int a, b, ab;

    switch (msg) {

    case WM_CREATE:
        break;

    case WM_PAINT:
        //月をビットマップ形式で描画していく作業
        g_img.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        g_img.bmi.bmiHeader.biWidth = 988;
        g_img.bmi.bmiHeader.biHeight = 741;
        g_img.bmi.bmiHeader.biPlanes = 1;
        g_img.bmi.bmiHeader.biBitCount = 32;
        g_img.bmi.bmiHeader.biCompression = BI_RGB;
        g_img.bmi.bmiHeader.biSizeImage = 988 * 741 * 4;
        g_img.bmi.bmiHeader.biXPelsPerMeter = 0;
        g_img.bmi.bmiHeader.biYPelsPerMeter = 0;
        g_img.bmi.bmiHeader.biClrUsed = 0;
        g_img.bmi.bmiHeader.biClrImportant = 0;

        g_img.lpBmpData = (BYTE *)malloc(988 * 741 * 4);

        RECT rect;

        hdc = BeginPaint(hWnd_bitmap, &ps);
        GetClientRect(hWnd_bitmap, &rect);
        hdc_mem = CreateCompatibleDC(hdc);

        for (a = 0; a < 741; a++) {
            for (b = 0; b < 988; b++) {

                ab = a * (988 * 4) + b * 4; //始めの項が行数、次の項が左から何ビット目かを表す。(blueの位置を決めている)

                // 以下は月の縁(円)の外側に対する処理(宇宙空間なので黒色で塗りつぶしている)
                int centerX = 988 / 2;
                int centerY = 741 / 2;
                if (sqrt(pow(b - centerX, 2) + pow(a - centerY, 2)) < 250) {
                    g_img.lpBmpData[ab] = 0xff;
                    g_img.lpBmpData[ab + 1] = 0xff;
                    g_img.lpBmpData[ab + 2] = 0xff;
                    g_img.lpBmpData[ab + 3] = 0;
                } else {
                    g_img.lpBmpData[ab] = 0;
                    g_img.lpBmpData[ab + 1] = 0;
                    g_img.lpBmpData[ab + 2] = 0;
                    g_img.lpBmpData[ab + 3] = 0;

                }
            }
        }

        hBmp = CreateDIBitmap(hdc, &(g_img.bmi.bmiHeader), CBM_INIT, g_img.lpBmpData, &(g_img.bmi), DIB_RGB_COLORS);
        free(g_img.lpBmpData);
        SelectObject(hdc_mem, hBmp);
        SetStretchBltMode(hdc, COLORONCOLOR);
        StretchBlt(hdc, 0, 0, 988, 741, hdc_mem, 0, 0, 988, 741, SRCCOPY);

        //メモリ軸を描画する関数を作り、ここで呼び出している(これはうまく描画できた)
        //disp_axes2(hdc, rect);

        //星の座標データを描画する関数を作り、ここで呼び出している(月をビットマップ形式で描画しない時は星がちゃんと描画されるが、月をビットマップ形式で描画すると消える)
        disp_star_xy(hdc, rect);

        DeleteDC(hdc);
        DeleteDC(hdc_mem);
        DeleteObject(hBmp);
        EndPaint(hWnd_bitmap, &ps);
        ReleaseDC(hWnd_bitmap, hdc);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return (DefWindowProc(hWnd_bitmap, msg, wp, lp));

    }

    return 0;

}

// 星の座標データを1チャンネル分ウィンドウに表示する関数
BOOL disp_star_xy(HDC hdc, RECT rect) //ただし、xy平面に描画する関数
{
    const int total_n2 = 40;
    COLORREF color;
    int i;

    color = RGB(255, 255, 255);/*RGB(255,241,0)*/    // チャンネル1は黄色
    int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める?
    double ppd = (rect.bottom - rect.top) / 10.0;        // 縦方向1div当たり何ピクセルか

    for (i = 0; i <= MAX_STAR; i++) {
//        star[i].x = star[i].x - (rect.right - rect.left) / 2;
//        star[i].y = (rect.bottom - rect.top) / 2 - star[i].y;
        int m;
        if (star[i].Mag < 0.0) {

            for (m = 0; m <= 8; m += 1) {
                SetPixel(hdc, star[i].x - m, star[i].y, RGB(228, 0, 127)/*RGB(255, 255, 255)*/);
                SetPixel(hdc, star[i].x, star[i].y - m, RGB(228, 0, 127)/*RGB(255, 255, 255)*/);
                SetPixel(hdc, star[i].x, star[i].y, /*RGB(255, 255, 255)*/RGB(228, 0, 127));
                SetPixel(hdc, star[i].x + m, star[i].y, RGB(228, 0, 127)/* RGB(255, 255, 255)*/);
                SetPixel(hdc, star[i].x, star[i].y + m, RGB(228, 0, 127)/*RGB(255, 255, 255)*/);
            }
        }

        else if (star[i].Mag < 2.0) {
            for (m = 0; m <= 6; m += 1) {
                SetPixel(hdc, star[i].x - m, star[i].y, RGB(255, 255, 255));
                SetPixel(hdc, star[i].x, star[i].y - m, RGB(255, 255, 255));
                SetPixel(hdc, star[i].x, star[i].y, RGB(255, 255, 255)/*RGB(173, 255, 47)*/);
                SetPixel(hdc, star[i].x + m, star[i].y, RGB(255, 255, 255));
                SetPixel(hdc, star[i].x, star[i].y + m, RGB(255, 255, 255));
            }
        }

        else if (star[i].Mag < 4.0) {
            for (m = 0; m <= 4; m += 1) {
                SetPixel(hdc, star[i].x - m, star[i].y, RGB(255, 255, 255));
                SetPixel(hdc, star[i].x, star[i].y - m, RGB(255, 255, 255));
                SetPixel(hdc, star[i].x, star[i].y, RGB(255, 255, 255)/*RGB(173, 255, 47)*/);
                SetPixel(hdc, star[i].x + m, star[i].y, RGB(255, 255, 255));
                SetPixel(hdc, star[i].x, star[i].y + m, RGB(255, 255, 255));
            }
        }

        else {
            SetPixel(hdc, star[i].x - 2, star[i].y, RGB(255, 255, 255));
            SetPixel(hdc, star[i].x, star[i].y - 2, RGB(255, 255, 255));
            SetPixel(hdc, star[i].x, star[i].y, RGB(255, 255, 255)/*RGB(173, 255, 47)*/);
            SetPixel(hdc, star[i].x + 2, star[i].y, RGB(255, 255, 255));
            SetPixel(hdc, star[i].x, star[i].y + 2, RGB(255, 255, 255));
        }

    }

    return TRUE;    // 戻り値TRUEを返す
}

2018/10/25 追記
ダイアログのコードを拝見しましたが、一見問題になりそうなところはありませんでした。

私が以前に指摘したのは disp_star_xy 関数における以下のコードブロックの一番下の 2 行です。おそらく星の X 座標を何らかの形で計算しているものと思われますが、X 座標から(rect.right-rect.left)/2 つまりは画面の半分の幅を減算しているため、この関数が 2 回呼び出された場合、画面の表示範囲内に収まっている X 座標はすべて範囲外になるという指摘です。それが InvalidateRect を2回と言ってたわけですが、実際のところ InvalidateRect を呼び出す以外に WM_PAINT が発行されることがあるので、InvalidateRect だけに限定されるわけではありません。
y 座標の計算も怪しい感じがします。

// 星の座標データを1チャンネル分ウィンドウに表示する関数  
BOOL disp_star_xy(HDC hdc, RECT rect, HWND hDlg) //ただし、xy平面に描画する関数  
{   
   COLORREF color;  
   HPEN hPen_xy;  
   int i;  

   color = RGB(255,255, 255);/*RGB(255,241,0)*/   // チャンネル1は黄色  
   hPen_xy = CreatePen(PS_SOLID, 9, color);  
   SelectObject(hdc, hPen_xy);                   // hdcで上記のペンを使うために選ぶ  
   HBRUSH hBrush_xy, h01dBrush_xy;  
   hBrush_xy = CreateSolidBrush(color);  
   h01dBrush_xy = (HBRUSH)SelectObject(hdc, hBrush_xy);  
   int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める?  
   double ppd = (rect.bottom - rect.top) / 10.0;       // 縦方向1div当たり何ピクセルか  

         for(i=0; i<=total_n2; i++){  
           star[i].x = star[i].x - (rect.right-rect.left)/2;
           star[i].y = (rect.bottom - rect.top) / 2 - star[i].y;

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/24 00:06

    星と月を同時に描画できない原因はそれなのでしょうか、、?星の座標の間違いは今は置いておいていいのかと、、。

    キャンセル

  • 2018/10/24 02:15

    回答に追記しました。完全に現象が再現可能なコードを提示していただけると解決は早いかと思います。

    キャンセル

  • 2018/10/25 01:26

    ダイアログプロシージャを載せました。

    キャンセル

  • 2018/10/25 18:53

    「InvalidateRect を 2 回以上呼び出すと X 座標がマイナスとなって描画位置がウィンドウの範囲に入らずに消えています。」に原因がありそうなのですが、文章がイマイチ理解できていません。よろしければもう少しだけわかりやすく説明お願い致します。自分の中でInvaridateRectは一回しか呼び出していないつもりになっています、、。

    キャンセル

  • 2018/10/25 19:55

    回答に追記してみました。ご確認ください。

    キャンセル

  • 2018/10/25 20:02

    星の元データを座標変換し、最終的な座標系としましてはウィンドウの中心を原点とする座標系です。ご指摘の二行は原点がウィンドウ左上からウィンドウ中心に持っていくための座標変換になります。なので間違いはないと考えております。実際、最近まで月と星を同時に描画できていたのですが、急に描画できなくなりました、、。

    キャンセル

  • 2018/10/25 20:15

    rect は単純に GetClientRect した結果が格納されているようですので、左上の座標を中心に移動させるのであれば、
    star[i].x += (rect.right - rect.left) / 2;
    star[i].y += (rect.bottom - rect.top) / 2;
    となるのではないでしょうか?
    とは言っても断片的なコードでは結論を出すのは難しいですね。Github なりに上げていただければアドバイスしやすいとは思います。

    キャンセル

  • 2018/10/25 20:44

    その書き方で書き換えるといつでも十字架が中心にいるだけの描画となりました。
    そうですよね、、githubの扱いにまだ慣れてないもので、、

    キャンセル

0

手続き的には問題ないように思います。
atata0319さんがおっしゃるように座標がおかしいのでは?

データの問題と手続きの問題を切り分けるために、まずは以下の
ように単純に横線だけを引くような処理が正しく動作することを確認し、
それからデータの検証をされてはいかがでしょうか?

// 星の座標データを1チャンネル分ウィンドウに表示する関数
BOOL disp_star_xy(HDC hdc, RECT rect, HWND hDlg) //ただし、xy平面に描画する関数
{
    COLORREF color;
    HPEN hPen_xy;
    int i;

    color = RGB(255, 255, 255);/*RGB(255,241,0)*/    // チャンネル1は黄色
    hPen_xy = CreatePen(PS_SOLID, 9, color);
    SelectObject(hdc, hPen_xy);                    // hdcで上記のペンを使うために選ぶ
    HBRUSH hBrush_xy, h01dBrush_xy;
    hBrush_xy = CreateSolidBrush(color);
    h01dBrush_xy = (HBRUSH)SelectObject(hdc, hBrush_xy);

    int nop = rect.right - rect.left + 1; //横方向のピクセル数を求める?
    double ppd = (rect.bottom - rect.top) / 10.0;        // 縦方向1div当たり何ピクセルか


    //-------------------------------------------------------
    //追記:横線描画
    for (int i = 0; i <  rect.right - rect.left; i++)
        SetPixel(hdc, i, rect.bottom / 2, RGB(255, 0, 0));
    //-------------------------------------------------------

    DeleteObject(hPen_xy);    // ペンを破棄する
    DeleteObject(hBrush_xy);
    DeleteObject(h01dBrush_xy);

    return TRUE;    // 戻り値TRUEを返す
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/25 18:51

    横線描画するとちゃんと描画されました。つまりデータに問題があると考えます。ここで、下のatata0319さんがアドバイスしてくださった、InvaridateRectを二回以上呼び出すとxが負になりという説明はどういう意味でしょうか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.40%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C

    4117questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3949questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Visual Studio

    2095questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。