비주얼 C++ 5.0 으로 다이얼로그에서 프린트가 되는 기능을 구현하고 있는데, 프린트 미리보기를 어떻게 구현해야 할지를 모르겠습니다. 방법을 알려주세요.
미리보기에 대한 함수는 다음과 같습니다.
void 뷰클래스명::OnFilePrintPreview()
{
CFilePrintPreviewState *pState = new CPrintPreviewState;
if(!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,
RUNTIME_CLASS(뷰클래스명, pState))
{
TRACE0("Error : DoPrintPreview failed");
AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
delete pState;
}
}
보다 자세한 것을 알고 싶으면 비주얼 C++의 도움말을 참조하세요. "도움말->SEARCH->QUERY" 에서 쿼리(Query) 안을 보면 에디트 박스가 있는데, 거기에서 CPrintPreviewState을 입력하고 엔터(혹은 밑에 있는 Query를 클릭)를 치면 됩니다.
CListCtrl에서 오른쪽 마우스 버튼을 눌렸을 때 데이터의 수정, 삽입, 삭제를 나타내는 팝업메뉴를 구현하고 싶습니다. 비주얼 C로 프로그래밍하는 것은 처음이라서 방법을 잘 모르겠습니다. 자세한 설명 부탁드립니다.
다음과 같이 해보면 해결할 수 있을 것입니다.
void CMyListCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu menu;
// 물론 IDR_POPUP이란 메뉴가 리소스 편집기로
// 작성되 있어야 합니다.
VERIFY(menu.LoadMenu(IDR_POPUP));
// 첫 번째 서브메뉴를
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CRect viewRect;
GetWindowRect(&viewRect);
// 화면에 출력합니다.
pPopup->TrackPopupMenu(
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x + viewRect.left,
point.y + viewRect.top,
this
);
CListCtrl::OnRButtonDown(nFlags, point);
}
다이얼로그 박스의 에디트 상자에서 값을 입력받아 부모 윈도우에 직선을 그리는 프로그래밍을 하고 있습니다. 다이얼로그 박스의 에디트 상자에서 입력받은 값을 뷰 클래스의 draw 함수와 연결하고 싶습니다.
질문한 내용의 해결 방법은 의외로 쉽습니다. 우선 다이얼로그 박스를 만들고 값을 입력받는 에디트 박스에 멤버 변수를 설정합니다. 이 과정은 클래스 위저드에 멤버 탭을 누르고 해당 컨트롤을 선택하면 변수를 입력할 수 있습니다. 여기서 만든 다이얼로그가 CInputDlg, 멤버 변수가 m_iVal이고, CView에서 특정 메뉴를 선택했다면 다음과 같이 하면 됩니다.
CView::OnInputValue()
{
CInputDlg MyDlg; // 객체를 하나 만듭니다.
MyDlg.m_iVal = 5; // 초기값을 여기서 설정해도 됩니다.
if(MyDlg.DoModal() == IDOK) { // 설정이 완료되면
// 대화 상자의 값을 읽어 들입니다.
m_iLineWidth = MyDlg.m_iVal;
//
// 원하는 작업을 수행합니다.
}
아스키 값을 Hex로 바꾸는 함수가 어떤 것인지 궁금합니다.
Hex 문자열을 정수값으로 변환하는 프로그램을 말하는 것 같은데 다음의 루틴을 이용해 보기 바랍니다. 런타임 라이브러리에는 그런 함수가 없는 걸로 알고 있습니다.
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#undef
//
UINT StrHexToInt(LPCTSTR str)
{
return (UINT)StrHexToLong(str);
}
ULONG StrHexToLong(LPCTSTR str)
{
CString work;
int nLength;
ULONG ulRetVal;
work = str;
if(strstr(str, "0x") != NULL)
work = strstr(str, "0x") + 2;
//
nLength = work.GetLength() - 1;
ulRetVal = 0;
work.MakeUpper();
for(int i=0; i<work.GetLength(); i++, nLength--) {
switch(work.GetAt(i)) {
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
ulRetVal += (work.GetAt(i) - '0') * (int)pow(16, nLength);
break;
case 'A' :
case 'B' :
case 'C' :
case 'D' :
case 'E' :
case 'F' :
ulRetVal += (10 + work.GetAt(i) - 'A') * (int)pow(16, nLength);
break;
default :
return ulRetVal = 0;
}
}
return ulRetVal;
}
십진수로 변환되면 다른 진수로도 충분히 바꿀 수 있을 것입니다.
프린트 프로그래밍을 하고 있습니다. 그런데 가로로 프린트를 해야 하는데 있어서 문제가
발생했습니다. 코드는 다음과 같습니다.
DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSpecVersion = DM_SPECVERSION;
dm.dmSize = sizeof(dm);
dm.dmFields = DM_ORIENTATION;
dm.dmOrientation = DMORIENT_LANDSCAPE;
pDC->ResetDC(&dm);
이렇게 지정을 했는데 문제는 그 다음 페이지부터 가로로 인쇄가 된다는 것입니다.
그리고 윈도우 NT 환경에서는 이 작업이 진행되지 않습니다. 해결 방법을 알려주세요.
가로 인쇄 제어를 다음과 같은 방법으로 해 보세요.
CDC dc;
CPrintDialog dlg1(FALSE), dlg2(FALSE);
dlg1.GetDefaults();
LPDEVMODE pDM = dlg1.GetDevMode();
// ++
if(pDM == NULL) {
AfxMessageBox(IDS_NOT_READY_PRINTER, MB_ICONSTOP);
return;
}
pDM->dmOrientation = DMORIENT_LANDSCAPE;
pDM->dmPrintQuality = 300;
pDM->dmYResolution = 300;
dlg2.m_pd.hDevMode = (HANDLE)pDM;
if(dlg2.DoModal() == IDOK)
dc.Attach(dlg2.GetPrinterDC()); // PrinterDC를 얻는다.
else
return;
DOCINFO di;
::ZeroMemory(&di, sizeof(DOCINFO));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = "Preset Pulse Graph Printing...";
if(dc.StartDoc(&di) > 0) {
// 필요한 데이터를 출력한다.
}
내 컴퓨터에 깔려있는 폰트를 얻으려면 어떻게 해야 하나요? 예를 들어서 리스트 박스나 콤보 박스에 내 컴퓨터의 폰트가 모두 보이게 하려면 어떤 함수를 써야 하는지 궁금합니다.
다음의 함수를 사용하면 됩니다.
int EnumFontFamiliesEx(HDC hdc, // DC 제어
LPLOGFONT lpLogFont, // 논리적인 폰트정보 포인터
FONTENUMPROC lpEnumFontFamExProc, // 콜백함수 포인터
LPARAM lParam, // 애플리케이션 데이터
DWORD dwFlags // reserved; must be zero
);
위 함수는 lpLogFont에 지정된 폰트들이 존재하면 lpEnumFontFamExProc에 등록된 CALLBACK 함수를 호출합니다. lpEnumFontFamExProc의 원형은 다음과 같습니다.
int CALLBACK EnumFontFamExProc(
ENUMLOGFONTEX *lpelfe, // 논리적인 폰트 데이터 포인터
NEWTEXTMETRICEX *lpntme, // 물리적인 폰트 데이터 포인터
int FontType, // 폰트 형태
LPARAM lParam // 정의된 애플리케이션 데이터
);
사용자는 이 함수에서 전달되는 폰트의 정보로 리스트 박스에 이름을 등록한다던가 아니면 다른 장소에 정보를 보관하면 됩니다. 이해를 돕기 위해 간단한 상황을 만들어 예를 보여드리겠습니다.
대화 상자에 IDC_LIST1 이라는 리스트 박스가 존재한다.
대화 상자가 열렸을 때 IDC_LIST1 박스에 폰트의 목록을 등록한다.
이때 대화 상자의 클래스명은 CMyFontDlg 이다.
우선 WM_INITDIALOG 메시지를 처리하는 onInitDialog 함수를 살펴보겠습니다.
BOOL CMyFontDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CListBox *pList = (CListBox *)GetDlgItem(IDC_LIST1);
if(pList != NULL) {
CMainFrame *pMain = (CMainFrame *)AfxGetMainWnd();
CView *pView = pMain->GetActiveView();
CDC *pDC = pView->GetDC();
LOGFONT lfont;
lfont.lfCharset = DEFAULT_CHARSET;
lfont.lfFaceName[0] = '\0'; // NULL 스트링 설정
lfont.lfPitchAndFamily = 0; // 모든 언어 선택
// MyFontCallBack 함수에 lParam 인자로 pList의
// 포인터를 전달합니다.
EnumFontFamiliesEx(pDC->m_hDC, &lfont,
MyFontCallBack,
(LPARAM)pList,
0 );
pView->ReleaseDC(pDC);
}
return TRUE;
}
// onInitDialog에서 EnumFontFamiliesEx 함수의 lParam 값에
// CListBox의 포인터를 넣었으므로 이 함수는 호출되면
// lParam에는 CListBox의 포인터가 전달된다.
// 그리고 계속 폰트 정보를 받으려면 0이 아닌 값을
// 리턴하고, 중지하려면 0을 리턴합니다.
int CALLBACK CMyFontDlg::MyFontCallBack(ENUMLOGFONTEX *lpelfe,
NEWTEXTMETRICEX *lpntme,
int FontType,
LPARAM lParam )
{
CListBox *pList = (CListBox *)lParam;
// listbox에 폰트 이름을 넣습니다.
// lpelfe의 다른 정보를 사용하시려면 도움말을 참조..
if(pList->AddString(lpelfe->elfLogFont.lfFameName) == LB_ERR)
return 0;
return 1;
}
동작을 살펴보면 만일 시스템에 '굴림체', '바탕체', '돋움체' 등 3개의 폰트가 설치돼 있다고 가정하면 MyFontCallBack 함수는 각 폰트마다 한번씩 호출되니까 총 3번 호출이 됩니다. 폰트에 대한 완전한 정보를 보관하고 싶으면 LOGFONT의 배열을 설정한 후 CallBack 함수가 호출될 때마다 그 정보를 저장하면 됩니다.
- The end of this article -
뷰에서 다이얼로그 박스를 만들지 않고 버튼을 뷰 화면에 만드는 방법을 알고 싶습니다.
일반적으로 CWnd에서 상속받은 윈도우에 버튼을 넣고 싶으면 다음과 같이 해보세요.
[1] 자신이 특별히 사용할 버튼을 CButton으로부터 상속받는다.
class iMyButton : public CButton
{
...
};
[2] 윈도우 클래스(CChildView)에 멤버로 버튼을 가지게 한다.
class CChildView : public CWnd
{
// Construction
public:
CChildView();
private:
iMyButton m_btn;
...
// 메시지 맵 함수를 생성
protected:
// {{AFX_MSG(CChildView)
...
afx_msg void onParentNotify(UINT message, LPARAM lParam);
// }} AFX_MSG
DECLARE_MESSAGE_MAP()
};
[3] 부모 윈도우가 생성될 때 버튼도 생성시킨다.
void CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CRect rcBtn(30, 50, 150, 90);
m_btn.Create("MyBtn", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
rcBtn, this, IDC_MY_BUTTON);
}
[4] 버튼을 생성/소멸할 때나 버튼을 눌렀을 때 특별한 처리를 해주고 싶으면 WM_PARENTNOTIFY 메시지를 처리해준다.
void CChildView::OnParentNotify(UINT message, LPARAM lParam)
{
switch(message) {
case WM_CREATE :
TRACE("CChildView::OnParentNotify --> WM_CREATE\n");
break;
case WM_DESTROY :
TRACE("CChildView::OnParentNotify --> WM_DESTROY\n");
break;
case WM_LBUTTONDOWN :
TRACE("CChildView::OnParentNotify --> WM_LBUTTONDOWN\n");
break;
case WM_MBUTTONDOWN :
TRACE("CChildView::OnParentNotify --> WM_MBUTTONDOWN\n");
break;
case WM_RBUTTONDOWN :
TRACE("CChildView::OnParentNotify --> WM_RBUTTONDOWN\n");
break;
}
}
[↓ Click! 비주얼 C++에서 프린트 미리보기 구현 / CListCtrl에서 팝업 메뉴 구현
다이얼로그 에디트 박스에서 값 입력받기 / 아스키 값을 Hex 값으로 바꾸는 함수
프린트시 가로 제어에 대해 / 시스템 폰트 얻기 ]
'IT_Programming > MFC · API' 카테고리의 다른 글
새창을 활성화시키기 않고 생성시키기 / 생성한 Class를 간단히 완전제거 (0) | 2007.12.25 |
---|---|
데이터 형변환 / VC++에서 시리얼 포트로 데이터 비트 발생 (0) | 2007.12.25 |
분할 윈도우에서 뷰 바꾸기 / MDI에서 Child LIST를 얻는 방법 (0) | 2007.12.25 |
프로그램 시작시 About박스를 표시 / 입력 컨트롤에서 허용하는 문자 제한 (0) | 2007.12.25 |
현재 작업중인 목록을 만들려면 / 리스트박스 깜박임 멈추기 (0) | 2007.12.25 |