رفتن به مطلب

برنامه نویسی گرافیک در c و ++c


poor!a

ارسال های توصیه شده

مقدمه:

اکنون بیش از 15 سال از انتشار کامپایلرهایی همچون ++Turbo C برای توسعه در محیط DOS می گذرد و در طی این سال ها امکانات و کتابخانه های بسیاری به زبان های C و ++C اضافه شده است از جمله STL در ++C که بسیاری از الگوریتم های معروف و پرکاربرد مانند پشته ، لیست پیوندی ،انواع صف ، انواع مرتب سازی ها و غیره را بدون نیاز به پیاده سازی در اختیار شما قرار می دهد که برای بهره مندی از این امکانات می بایست از کامپایلرهای جدید و به روز 32/64 بیتی استفاده کرد، از جمله:

++Visual C و ++minGW/Dev C (کد باز و رایگان) و C++‎Builder و ...

 

نکته: امروزه در محیط های آموزشی سراسر دنیا از نسخه های رایگان این کامپایلرها و یا کامپایلرهای کد باز به عنوان جایگزینی برای ++Turbo C استفاده می کنند.

 

سوال- آیا می توان از توابع گرافیکی قدیمی graphics.h در محیط های جدید برنامه نویسی مانند Visual C++ /Borland C++‎builder / gcc / mingw و ... استفاده کرد؟

 

خیر، این توابع از جمله توابع 16 بیتی قدیمی و منسوخ شده بورلند می باشند که برخلاف تفکر برخی از نوآموزان، جزئی از این زبان نیست.

 

لذا برای توسعه های جدید، چندین راه وجود دارد:

 

روش 1) اولین و بهترین روش برای کار با گرافیک مخصوصا برای دانشجویان، روی آوردن به نوشتن برنامه های غیر کنسولی می باشد (با زبان C++‎/C) همانند سایر برنامه های ویندوز اما فقط در سطح ساده و برای نمایش اشکال گرافیکی و البته بدون داخل شدن در مباحث های پیشرفته واسط کاربری. (به این شکل که پنجره ای ایجاد نموده و در آن شروع به رسم اشکال گرافیکی کنید)

 

در ویندوز دوستان می توانند با توابع گرافیکی GDI و +GDI از طریق شیوه های win32 و MFC با کامپایلرهای ++VC و ++DevC و یا از طریق VCL با کامپایلر C++‎Builder این کار را انجام دهند.

توجه کنید که با مطالعه بخش گرافیکی یکی از لینک های زیر در مدتی بین دو هفته تا یک ماه قادر به ایجاد برنامه های گرافیکی، بازی ساده گرافیکی و همین طور کار با mouse و keyboard خواهید بود:

 

برای win32 (سطح پایین ،اما یادگیری با مراجع زیر بسیار راحت می باشد):

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

برای MFC (کمی ساده تر از مورد فوق)

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

برای VCL

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

لینک به دیدگاه

-------------------------------

روش 2) استفاده از توابع کنسولی مایکروسافت برای command prompt ویندوز ، لیست این توابع در لینک زیر موجود می باشد:

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

در این روش شما باید معادل توابع graphics.h را که در محیط Turbo C و کامپایلر های سری قدیم بورلند وجود داشت را با توابع 32 بیتی کنسولی مایکروسافت پیاده سازی کنید، به عنوان مثال برای gotoxy و clrscr لینک زیر را مشاهده کنید:

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.
برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

توجه به این مورد ضروری می باشد که محیط command prompt ویندوز محیطی کاملا متفاوت از محیط 16 بیتی DOS می باشد و نباید انتظار داشته باشید که تمامی امکانات 16 بیتی قدیمی توسط این کامپایلرها به همان شکل در اختیار شما قرار گیرد، از جمله رسم اشیاء گرافیکی همانند قبل در این روش امکان پذیر نیست و جداول و اشکال ساده می بایست توسط خطوط و کارکترها پیاده سازی شوند، اما این قابلیت در اختیار شما قرار می گیرد که بتوانید از اکثر توابع پیشرفته سیستم عامل در محیط کنسول استفاده کنید.

 

لینک زیر شامل مثال ها و آموزش های کامل در زمینه استفاده از همین توابع کنسولی win32 می باشد، پس قبل از هر کاری ابتدا نگاهی به نمونه های پیاده سازی شده در این سایت بیاندازید:

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

-------------------------------

روش 3) روش ساده تر از مورد قبل، استفاده از کتابخانه های 32 بیتی آماده غیر استاندارد و معادل graphic.h می باشد که برخی از آن ها open source (کد باز) نیز می باشد، مانند WinBGI که می توانید فایل های آن را از صفحه زیر دانلود کرده و استفاده کنید:

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

توجه کنید که این کتابخانه از توابع گرافیکی win32 استفاده می کند و برای نمایش آن ها پنجره سیاه دیگری همانند کنسول باز می شود که قادر هستید در آن اشکال گرافیکی را همانند برنامه های ویندوز به سادگی برنامه های گرافیکی Turbo C رسم کنید.

 

-------------------------------

روش 4) آخرین و بدترین روش برگشتن به محیط قدیمی ++Turbo C و استفاده از همان توابع گرافیکی graphics.h می باشد که در برخی کتاب ها از جمله کتاب C جعفرنژاد قومی به آن پرداخته شده است. (البته امیدوارم به عنوان یک دانشجو و یا حتی کسی که می خواهد در حد پروژه های ساده با این زبان آشنا شود این گزینه را انتخاب نکنید)

لینک به دیدگاه

برخی از دوستان در مورد سایت هایی برای کار با mouse و keyboard در کنار کار گافیکی سوال کردند که می توانند از نمونه کدهای لینک های زیر شروع به یادگیری کنند (ابتدا مطالعه لینک های قرار داده شده در تاپیک قبل برای win32 ضروری است):

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

برای یک نمونه خوب حتما Drawing Lines with the Mouse را در لینک فوق مطالعه کنید.

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

در لینک فوق نمونه های پیام WM_LBUTTONDOWN و WM_LBUTTONUP را برای پردازش mouse بررسی کند.

لینک به دیدگاه

[h=2]آموزش مقدماتی گرافیک از طریق win32[/h]

هدف از این آموزش ترسیم اشکال گرافیکی ساده در محیط ویندوز هست.

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

پیش نیاز این آموزش:

- مطالعه دو لینک آموزشی در پست اول برای آشنایی با مفاهیم ساخت پنجره و پیام ها

- استفاده از کامپایلر visual C++‎ 2005 یا بالاتر

 

 

نحوه انجام:

1) ابتدا به منوی new رفته و یک پروژه از نوع win32 project با نام "rect1" و مقادیر پیش فرض بسازید (دقت کنید که console نباشد).

پروژه با چند فایل ساخته می شود، که ما با فایل rect1.cpp کار داریم.

 

2) برای رسم یک مربع ساده به این شکل عمل کنید:

در قسمت case و پیام WM_PAINT کار های گرافیکی در قسمت client یا همان قسمت سفید انجام می شود، دقت کنید که کد های گرافیکی باید مابین دو دستور BeginPaint و EndPaint نوشته شوند.

 

برای شروع مربعی بدون رنگ رسم می کنیم، کد را به شکل زیر تغییر دهید:

 
[TABLE]

[TR]

[TD=class: gutter]1

2

3

4

5

6

7

8

9

[/TD]

[TD=class: code]case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

 

Rectangle(hdc, 100, 100, 200, 200);
// Empty

 

EndPaint(hWnd, &ps);

break;

 

[/TD]

[/TR]

[/TABLE]

 

3) حال در کنار آن مربعی با یکی از رنگ های پیش فرض سیستم رسم می کنیم:

 

 
[TABLE]

[TR]

[TD=class: gutter]1

2

3

4

5

6

7

8

9

10

11

12

[/TD]

[TD=class: code]case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

 

Rectangle(hdc, 100, 100, 200, 200); // Empty

 

SelectObject (hdc, GetStockObject (LTGRAY_BRUSH)) ;

Rectangle(hdc, 300, 100, 400, 200); // Filled by light gray color

 

EndPaint(hWnd, &ps);

break;

 

[/TD]

[/TR]

[/TABLE]

 

 

در کد فوق با استفاده از دستور SelectObject یکی از اشیاء را مانند قلم ، مداد ، عکس و غیره را برای رنگ آمیزی و ترسیم می توانید انتخاب کنید. در این مورد ما با استفاده از تابع GetStockObject یکی از قلم های پیش فرض سیستم را انتخاب کردیم که خاکستری روشن هست. (سایر انواع : BLACK_BRUSH، HOLLOW_BRUSH ، WHITE_BRUSH ، BLACK_PEN و ....)

 

 

4) برای ساختن یک brush یا قلم دلخواه (با رنگ دلخواه) به این شکل عمل می کنیم:

 

- ابتدا قلم را در پیام WM_CREATE می سازیم (این پیام را خودتان در بخش case ها اضافه کنید )، هر چیزی که در بخش WM_CREATE نوشته شود در هنگام شروع برنامه قبل از هر چیزی اجرا می شود .

 

- از تابع CreateSolidBrush و ماکرو RGB برای ساخت قلم و رنگ استفاده می کنیم.

 

- hbrush از نوع HBRUSH باید قبل از switch تعریف شود و حتما static باشد چون فقط یک مرتبه در شروع برنامه مقدار دهی می شود.

 

- وقتی خودمان قلمی درست می کنیم باید در انتهای برنامه فضای اختصاص داده شده به آن را آزاد کنیم پس در قسمت WM_DESTROY در هنگام بستن برنامه را فراخوانی DeleteObject می کنیم .

 

- SelectObject آخر برای این است که همراه پس از انجام رسم ، قلم قبلی که پیش فرض سیستم بود انتخاب و آماده برای سایر موارد رسم بعدی شود.

 

پس تابع به شکل زیر تغییر داده می شود:

 
[TABLE]

[TR]

[TD=class: gutter]1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

[/TD]

[TD=class: code]LRESULT CALLBACK WndProc(HWND hWnd, UINT message,

WPARAM wParam, LPARAM lParam)

{

int wmId, wmEvent;

PAINTSTRUCT ps;

HDC hdc;

static HBRUSH hbrush, hbrushOld;
// must be static

 

switch (message)

{

case WM_CREATE:

// Create a red brush

hbrush = CreateSolidBrush(RGB(255, 0, 0));

 

break;

 

case WM_COMMAND:

// **... I removed codes ... **

break;

 

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

 

Rectangle(hdc, 100, 100, 200, 200); // Empty

 

SelectObject (hdc, GetStockObject (LTGRAY_BRUSH)) ;

Rectangle(hdc, 300, 100, 400, 200); // Filled by light gray color

 

// Select the new brush and draw

hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);

Rectangle(hdc, 500, 100, 600, 200); // Filled by light gray color

SelectObject(hdc, hbrushOld); // select old brush

 

EndPaint(hWnd, &ps);

break;

 

case WM_DESTROY:

PostQuitMessage(0);

DeleteObject(hbrush);

 

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

 

[/TD]

[/TR]

[/TABLE]

 

5) سایر توابعی که می توانید از آن ها برای رسم اشکال استفاده کنید:

Ellipse ، Polygon ، RoundRect ، Pie ، Chord ، Arc ، LineTo ، Polyline و ...

 

 

در آینده نحوه کار با mouse و keyboard برای رسم اشکال نیز توضیح داده خواهد شد.

 

 

 
لینک به دیدگاه

هدف از این آموزش ترسیم مستطیل در محیط ویندوز با حرکات mouse هست و در این قسمت شما با پیام های mosue آشنا می شوید.

 

[TABLE]

[TR]

[TD=class: gutter][/TD]

[/TR]

[/TABLE]

 

 

ابتدا تابعی با نام DrawBorder را برای ترسیم یک مستطیل تعریف می کنیم.

 

- دقت کنید که از آن جایی که در خارج از پیام WM_PAINT در حال رسم هستیم لذا ابتدا هندل DC یا همان display device context را برای انجام کارهای گرافیکی قسمت client area باید با استفاده از GetDC دریافت کنید و در پایان ترسیم نیز با ReleaseDC آزاد کنید.

 

- تابع SetROP2 با فلگ R2_NOT باعث می شود مستطیل ما با رنگی معکوس زنگ زمینه در هنگام drag کردن mouse نمایش داده شود.

 

 

 

 

[TABLE]

[TR]

[TD=class: gutter]1

2

3

4

5

6

7

8

9

10

11

12

[/TD]

[TD=class: code]void DrawBorder(HWND hwnd, POINT ptBeg, POINT ptEnd)

{

HDC hdc ;

hdc = GetDC (hwnd) ;

 

SetROP2 (hdc, R2_NOT) ;

SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;

Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;

 

ReleaseDC (hwnd, hdc) ;

}

 

[/TD]

[/TR]

[/TABLE]

 

تابع WndProc را همانند مثال قبل برای پیام ها به شکل زیر تغییر دهید:

 

 

 

[TABLE]

[TR]

[TD=class: gutter][/TD]

[/TR]

[/TABLE]

 

 

 

 

 

 

[TABLE]

[TR]

[TD=class: gutter]1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

[/TD]

[TD=class: code]LRESULT CALLBACK WndProc(HWND hWnd, UINT message,

WPARAM wParam, LPARAM lParam)

{

int wmId, wmEvent;

HDC hdc ;

PAINTSTRUCT ps ;

static BOOL drawing, drawBox ;

static POINT ptBeg, ptEnd, ptBoxBeg, ptBoxEnd ;

 

switch (message)

{

case WM_LBUTTONDOWN :

ptBeg.x = ptEnd.x = LOWORD (lParam) ;

ptBeg.y = ptEnd.y = HIWORD (lParam) ;

 

drawing = TRUE ;

return 0 ;

 

case WM_MOUSEMOVE :

if (drawing)

{

SetCursor (LoadCursor (NULL, IDC_CROSS)) ;

DrawBorder (hWnd, ptBeg, ptEnd) ; // clean previous drawing

 

ptEnd.x = LOWORD (lParam) ;

ptEnd.y = HIWORD (lParam) ;

 

DrawBorder (hWnd, ptBeg, ptEnd) ;

}

return 0 ;

 

case WM_LBUTTONUP :

if (drawing)

{

DrawBorder (hWnd, ptBeg, ptEnd) ;

 

ptBoxBeg = ptBeg ;

ptBoxEnd.x = LOWORD (lParam) ;

ptBoxEnd.y = HIWORD (lParam) ;

 

SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

 

drawing = FALSE ;

drawBox = TRUE ;

InvalidateRect (hWnd, NULL, TRUE) ;

}

return 0 ;

 

case WM_PAINT :

hdc = BeginPaint (hWnd, &ps) ;

 

if (drawBox)

{

SelectObject (hdc, GetStockObject (LTGRAY_BRUSH)) ;

Rectangle (hdc, ptBoxBeg.x, ptBoxBeg.y, ptBoxEnd.x, ptBoxEnd.y) ;

}

 

if (drawing)

{

SetROP2 (hdc, R2_NOT) ;

SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;

Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;

}

 

EndPaint (hWnd, &ps) ;

return 0 ;

 

case WM_COMMAND:

wmId = LOWORD(wParam);

wmEvent = HIWORD(wParam);

// Parse the menu selections:

switch (wmId)

{

case IDM_about:

DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);

break;

case IDM_EXIT:

DestroyWindow(hWnd);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

break;

 

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ;

 

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

 

// Message handler for about box.

INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

{

UNREFERENCED_PARAMETER(lParam);

switch (message)

{

case WM_INITDIALOG:

return (INT_PTR)TRUE;

 

case WM_COMMAND:

if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

{

EndDialog(hDlg, LOWORD(wParam));

return (INT_PTR)TRUE;

}

break;

}

return (INT_PTR)FALSE;

}

 

[/TD]

[/TR]

[/TABLE]

 

[TABLE]

[TR]

[TD=class: gutter]

[/TD]

[/TR]

[/TABLE]

پیام های mouse مورد استفاده :

- پیام WM_LBUTTONDOWN وقتی فراخوانی می شود که کلیک چپ mouse زده می شود.

 

- پیام WM_MOUSEMOVE وقتی که mouse در حال حرکت می باشد.

لذا با یک متغیر bool تست می کنیم که حتما پیام LBUTTONDOWN مقدار true داشته باشد و سپس عملیات انجام شود.

 

- پیام WM_LBUTTONUP وقتی کلیک چپ mouse آزاد می شود

پس از پایان این پیام تابع InvalidateRect را فراخوانی می کنیم تا با رفرش کردن تصویر در قسمت WM_PAINT ترسیم نهایی مستطیل انجام شود (متغیر drawBox وقتی true می شود)

 

- با استفاده از lParam های در پیام های mouse مختصات x و y را دریافت می کنیم.

 

- تابع SetCursor نشان mosue را به یک شکل دیگر مانند + تغییر می دهد.

لینک به دیدگاه

دوستانی که می خواهند یک text editor برای محیط کنسول طراحی کنند و از توابع گرافیکی قدیمی بورلند نیز استفاده نکنند، می توانند برنامه زیر را دریافت و مطالعه کنند:

 

برای مشاهده این محتوا لطفاً ثبت نام کنید یا وارد شوید.

 

 

این برنامه توسط روش دوم نوشته شده است که در پست اول همین تاپیک ذکر شده است. یعنی همان استفاده از توابع کنسولی مایکروسافت و پیاده سازی gotoxy و غیره .

البته خود این برنامه در محیط ++DevC نوشته شده است، اما به این شکل در کامپایلر های دیگر ویندوز مانند ++Visual C نیز قابل استفاده است.

 

توجه کنید که از توابع قدیمی گرافیکی بورلند استفاده نشده است و در کامپایلرهای قدیمی مانند ++Turbo C نیز قابل اجرا نیست

لینک به دیدگاه

شما می توانید کل برنامه را در Notepad بنویسید و با کامپایلر نسخه command line کامپایل کنید. (همه کامپایلر ها شامل VC++‎‎‎ و gcc این قابلیت را دارند)

 

اگر می خواهید برنامه شما اشکال گرافیکی داشته باشد در محیط کنسول (صفحه سیاه) نمی توانید اشکال گرافیکی را نمایش دهید. (به این در ویندوز می گویند Win32 console)

 

اگر می خواهید اشکال گرافیکی داشته باشید (مثلا فقط یک دایره)، آن وقت در تابع main باید یک پنجره خالی ویندوز تولید کرده و با تابع گرافیکی ویندوز (کتابخانه GDI یا GDI+) یک دایره در پنجره رسم کنید. (به این شیوه می گویند win32 غیر کنسولی)

.

 

ضمنا برای چندمین مرتبه: شما با win32 تقریبا همه نوع برنامه می توانید بنویسید، فقط کدنویسی معمولا بیشتر می شود. MFC نیز از win32 استفاده می کند.

لینک به دیدگاه

به گفتگو بپیوندید

هم اکنون می توانید مطلب خود را ارسال نمایید و بعداً ثبت نام کنید. اگر حساب کاربری دارید، برای ارسال با حساب کاربری خود اکنون وارد شوید .

مهمان
ارسال پاسخ به این موضوع ...

×   شما در حال چسباندن محتوایی با قالب بندی هستید.   حذف قالب بندی

  تنها استفاده از 75 اموجی مجاز می باشد.

×   لینک شما به صورت اتوماتیک جای گذاری شد.   نمایش به صورت لینک

×   محتوای قبلی شما بازگردانی شد.   پاک کردن محتوای ویرایشگر

×   شما مستقیما نمی توانید تصویر خود را قرار دهید. یا آن را اینجا بارگذاری کنید یا از یک URL قرار دهید.

×
×
  • اضافه کردن...