Функция CreateDC возвращает значение NULL

#c #mfc #windows-ce

#c #mfc #windows-ce

Вопрос:

У меня проблема с CreateDC функцией. После вызова hDC дескриптора он возвращается NULL .

Это фрагмент кода, в котором вызывается функция после нажатия кнопки. m_pPrint является указателем на Print класс, в котором определены функции, связанные с контекстом устройства. Он инициализируется как

 m_pPrint = new Print


void MainMenuDlg::OnBnClickedMenuPrint()
{
    
    int nPatientID = m_patientsDlg->m_pCurrSelData->nPatientId;
    int nExamID = m_patientsDlg->m_pCurrSelData->nExamId;
    m_outPrintingManager->PrintEcgSignal(nPatientID, nExamID);
    short* sigPointer = m_outPrintingManager->GetSamplesPointer();

    m_pPrint->PrinterInit();
    m_pPrint->PageSetup();
    m_pPrint->StartPrint();
    m_pPrint->SignalAdjust(80,1000);
    m_pPrint->DrawECG(sigPointer, 12, 9000);
    m_pPrint->EndPrint();

    
}
 

Это заголовочный файл Print класса

     class Print
{
protected:

    HWND hwnd;
    CDC hDC;
    int start_x;
    int start_y;
    //LPCWSTR captions[12] = { L" I ", L" II", L"III", L"aVR", L" aVL ", L"aVF", L"V1", L"V2", L"V3", L"V4", L"V5", L"V6" };
    LPCWSTR captions[12];
    int limit_x;
    int limit_y;
    int printmode;
    int width;
    int new_sign_len;
    int channel_nr;
    int startSample;
    int channels[13];
    int mode;
    float sig_speed;
    float amplitude;
    int offset;
    int channel_start;
    int channel_stop;
    int tmp_channel;
    float frequency;
    int space;
    int page;
    BOOL orientation;
public:
    Print();
    ~Print();
    int Print();
    BOOL PrinterInit();
    BOOL PageSetup();
    BOOL StartPrint();
    BOOL DrawGrid(int start_x, int start_y, int limit_x, int limit_y, int width);
    BOOL EndPrint();
    void DrawECG(short * pointer, int channel_nr, int channelLength);
    void SignalAdjust(int start_x, int limit_x);
    void rysujEKG_Vertical(short * pointer, int start_x = 20, int limit = 1100, int offset = 60);
    void rysujEKG_Horizont(short * pointer, int start_x, int limit, int offset);
    void setSpeed(float s);
    void setAmplitude(float a);
    void setPrintMode(int printmod);
    void setChannelStart(int chan_start);
    void setChannelOrder(int * pointer_channel);
    void setChannelStop(int chan_stop);
    void setChannelNr(int chan_nr);
    void setSpace(int sp);
    void setPage(int pg);
    void setSignalLength(int sl);
    void setOrientation(int orient);
    void setStartSample(int startsample);
    float getSpeed();
    float getAmplitude();
    float getFrequency();
    int getChannelNr();
    int getPrintMode();
    int getChannelStart();
    int getChannelStop();
    int getSpace();
    void DrawScaleVertic(int x, int y);
    void DrawExaminationTextBox_Horizont(int start_x, int start_y, int stop_y);

}
 

;

И функция PageSetup , которая CreateDC вызывает. hDC является CDC типом. Инициализируется как CDC hDC

 BOOL Print::PageSetup()
{

    ZeroMemory(amp;psd, sizeof(psd));
    psd.lStructSize = sizeof(psd); // psd is member of PAGESETUPDLG structure
    psd.hwndOwner = NULL;
    psd.hDevMode = hMode; // Don't forget to free or store hDevMode.
    psd.hDevNames = hNames; // Don't forget to free or store hDevNames.
    psd.Flags = PSD_INHUNDREDTHSOFMILLIMETERS | PSD_MARGINS | PSD_MINMARGINS;
    psd.rtMargin.top = user_margins.top;
    psd.rtMargin.left = user_margins.left;
    psd.rtMargin.right = user_margins.right;
    psd.rtMargin.bottom = user_margins.bottom;
    psd.rtMinMargin.top = 100;
    psd.rtMinMargin.left = 100;
    psd.rtMinMargin.right = 100;
    psd.rtMinMargin.bottom = 100;
    psd.ptPaperSize.x = papersize.x;
    psd.ptPaperSize.y = papersize.y;
    psd.lpfnPagePaintHook = NULL;
    lf_vertic.lfHeight = 30; // is member of LOGFONT structure
    lf_vertic.lfWidth = 0;
    //lf.lfOrientation = 2700;
    lf_vertic.lfEscapement = 0;
    lf_vertic.lfUnderline = FALSE;
    lf_vertic.lfWeight = FW_BOLD;
    lf_horizont.lfHeight = 30;
    lf_horizont.lfWidth = 0;
    //lf.lfOrientation = 2700;
    lf_horizont.lfEscapement = 2700;
    lf_horizont.lfUnderline = FALSE;
    lf_horizont.lfWeight = FW_BOLD;

    lf_exam_param.lfHeight = 30;
    lf_exam_param.lfWidth = 0;
    lf_exam_param.lfEscapement = 2700;
    lf_exam_param.lfUnderline = FALSE;
    lf_exam_param.lfWeight = FW_NORMAL;

    hFontVertic = CreateFontIndirect(amp;lf_vertic);
    hFontHorizont = CreateFontIndirect(amp;lf_horizont);
    hFontExamParam = CreateFontIndirect(amp;lf_exam_param);
    PRINTDLG pd;
    pd.hwndOwner = NULL;
    pd.rcMargin.top = 3000;


    if (PageSetupDlg(amp;psd) == TRUE)
    {
        memcpy(amp;dm, (DEVMODE *)(psd.hDevMode), sizeof(DEVMODE));
        lstrcpy(DriverName, ((TCHAR *)((BYTE *)psd.hDevNames   ((DEVNAMES *)psd.hDevNames)->wDriverOffset)));
        lstrcpy(DeviceName, ((TCHAR *)((BYTE *)psd.hDevNames   ((DEVNAMES *)psd.hDevNames)->wDeviceOffset)));
        lstrcpy(OutputName, ((TCHAR *)((BYTE *)psd.hDevNames   ((DEVNAMES *)psd.hDevNames)->wOutputOffset)));
        lstrcpy(OutputName, ((TCHAR *)((BYTE *)psd.hDevNames   ((DEVNAMES *)psd.hDevNames)->wOutputOffset)));
        user_margins.left = psd.rtMargin.left;
        user_margins.right = psd.rtMargin.right;
        user_margins.bottom = psd.rtMargin.bottom;
        user_margins.top = psd.rtMargin.top;
        papersize.x = psd.ptPaperSize.x;
        papersize.y = psd.ptPaperSize.y;
        dm.dmPrintQuality = 300;
        dm.dmPaperSize = DMPAPER_A4;
        hDC.CreateDC(DriverName, DeviceName, OutputName, amp;dm);
        return TRUE;
}
 

Отладка hDC

Комментарии:

1. Если CreateDC возвращает значение null, вызовите GetLastError, чтобы получить представление о причине сбоя.

2. Элемент hDevMode PAGESETUPDLGA содержит дескриптор объекта DEVMODE. Вы уверены, что можете просто привести его к a DEVOMOD* . Я бы проверил, что члены структуры DEVMODE правдоподобны. Обычно HGLOBAL требует GlobalLock для получения указателя на данные. — Поскольку вы запускаете ее в отладчике, должно быть достаточно распечатать структуру DEMOVE в журнале отладчика.

3. @500 CreateDC (как и большинство GDI) предшествует введению отчетов об ошибках для каждого потока. При сбое не будет установлена последняя ошибка вызывающего потока.

4. @IInspectable: документация Windows CE SDK предполагает это.

5. Windows CE — это другая ОС. Он не использует ни свое ядро, ни оконный код с линейкой продуктов NT. Его API похож на Windows API, хотя часто с разными контрактами (как в этом случае). Вызов GetLastError в ответ на неудачный вызов CreateDC в Windows не вернет значимого значения.

Ответ №1:

Когда я работаю со DEVMODE структурой, я делаю это так:

 void CCommunityTalksApp::GetPageSettings(CPrintInfo *pInfo, short amp;dmPaperSize, short amp;dmOrientation)
{
    PRINTDLG    pd;
    DEVMODE FAR *pDevMode = nullptr;

    pd.lStructSize = (DWORD)sizeof(PRINTDLG);

    if(pInfo == nullptr)
    {
        if(GetPrinterDeviceDefaults(amp;pd))
        {
            // protect memory handle with ::GlobalLock and ::GlobalUnlock
            pDevMode=(DEVMODE FAR *)::GlobalLock(m_hDevMode);
        }
    }
    else
    {
        // protect memory handle with ::GlobalLock and ::GlobalUnlock
        pDevMode=(DEVMODE FAR *)::GlobalLock(pInfo->m_pPD->m_pd.hDevMode);
    }

    if(pDevMode != nullptr)
    {
        // is it set to landscape
        dmPaperSize = pDevMode->dmPaperSize;
        dmOrientation = pDevMode->dmOrientation;
    }

    if(pInfo == nullptr)
    {
        ::GlobalUnlock(m_hDevMode);
    }
    else
    {
        ::GlobalUnlock(pInfo->m_pPD->m_pd.hDevMode);
    }
}
 

Как вы можете видеть, я использую методы ::GlobalLock и ::GlobalUnlock :

  • pDevMode=(DEVMODE FAR *)::GlobalLock(m_hDevMode)
  • pDevMode=(DEVMODE FAR *)::GlobalLock(pInfo->m_pPD->m_pd.hDevMode)
  • ::GlobalUnlock(m_hDevMode)
  • ::GlobalUnlock(pInfo->m_pPD->m_pd.hDevMode)