嗯?听说你在Windows系统上C语言程序?那你对控制台窗口了解多少?
Linux、Mac 的Shell以后有时间再玩….
听说你会写Helloworld
程序,我猜一定是这个样子的:
#include<stdio.h>
int main() {
return 0&printf("Hello, world!\n");
}
那么问题来了,你会不会写下面这种风格的?
#include<Windows.h>
int main() {
HWND hWnd = GetConsoleWindow();
HDC hdc = GetDC(hWnd);
HFONT font = CreateFont(
64, // nHeight
0, // nWidth
-50, // nEscapement
20, // nOrientation
FW_BOLD, // nWeight
TRUE, // bItalic
TRUE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS,
L"Arial" // nPitchAndFamily Arial
);
SelectObject(hdc, font);
SetBkColor(hdc, 0x000000);
SetTextColor(hdc, RGB(100,149,237));
TextOut(hdc, 30, 30, L"Hello, world!", 13);
ValidateRect(hWnd, 0);
return 0;
}
绘制文字算什么,还能在控制台窗口上添加按钮 ↓ ↓ ↓,没错就是每天都会点的那种按钮,点了还会有反应!
#include<Windows.h>
#include<iostream>
int main() {
HWND hWnd = GetConsoleWindow();
HFONT font = CreateFont(
20, // nHeight
0, // nWidth
0, // nEscapement
0, // nOrientation
FW_NORMAL, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS,
L"新宋体" // nPitchAndFamily Arial
);
HWND b1 = CreateWindow(
L"BUTTON", // predefined class
L"确定", // button text
WS_VISIBLE | WS_CHILD, //values for buttons.
100, // starting x position
100, // starting y position
100, // button width
40, // button height
hWnd, // parent window
0, // No menu
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
HWND b2 = CreateWindow(
L"BUTTON", // predefined class
L"取消", // button text
WS_VISIBLE | WS_CHILD, //values for buttons.
240, // starting x position
100, // starting y position
100, // button width
40, // button height
hWnd, // parent window
0, // No menu
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
SendMessage(b1, WM_SETFONT, (WPARAM)font, 1);
SendMessage(b2, WM_SETFONT, (WPARAM)font, 1);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.hwnd==b1 && msg.message== WM_LBUTTONDOWN) {
MessageBox(hWnd, L"点击了确定按钮", L"Hello", MB_ICONINFORMATION);
}
if (msg.hwnd == b2 && msg.message == WM_LBUTTONDOWN) {
MessageBox(hWnd, L"点击了取消按钮", L"Hello", MB_ICONINFORMATION);
}
}
}
还有更多玩法,既然可以绘制不同字体的文字,当然也可以绘制图片
了解音频视频编码的同学把控制台窗口改造成视频播放器也是可以的!
#include<Windows.h>
#include<stdio.h>
#include<gdiplus.h>
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;
int main() {
Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
HWND hWnd = GetConsoleWindow();
HDC hdc = GetDC(hWnd);
Image* pImage = Image::FromFile(L"Flandre.jpg");
if (!pImage) {
printf("无法打开图片 Flandre.jpg");
return -1;
}
Graphics graphics(hdc);
graphics.DrawImage(pImage, 0, 0, pImage->GetWidth()/2.5, pImage->GetHeight()/2.5);
return 0;
}
接下来是一个圆周运动停不下来的控制台窗口(Enter键终止)
#include<Windows.h>
#include<math.h>
#include<stdio.h>
#define PI 3.14159265
#define POSCOUNT 10
int position[POSCOUNT][2];
DWORD WINAPI task(VOID* hWnd) {
RECT rc;
GetWindowRect((HWND)hWnd, &rc);
int i = 0;
while (true)
{
MoveWindow(
(HWND)hWnd, position[i][0],
position[i][1],
rc.right - rc.left,
rc.bottom - rc.top,
TRUE);
ShowWindow((HWND)hWnd, SW_SHOW);
printf("当前窗口位置: %d, %d\n", position[i][0], position[i][0]);
i++;
if (i >= POSCOUNT)
i = 0;
Sleep(20);
}
}
int main() {
HWND hWnd = GetConsoleWindow();
int i = 0;
for (;i < POSCOUNT;i++) {
position[i][0] = 100 * sin(PI * 2 * i / POSCOUNT) + 300;
position[i][1] = 100 * cos(PI * 2 * i / POSCOUNT) + 300;
}
CreateThread(0, 0, task, hWnd, 0, 0);
getc(stdin);
}
最后呢,在控制台窗口上来一发3D渲染好了
#include<d3d9.h>
#include<d3dx9.h>
#pragma comment(lib, "winmm.lib")
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Our texture
LPDIRECT3DVERTEXBUFFER9 g_pVBGeometry = NULL; // Buffer to hold vertices
LPDIRECT3DINDEXBUFFER9 g_pIBGeometry = NULL; // A structure for our custom vertex type. We added texture coordinates
struct Vertex {
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
FLOAT u, v;
};
#define VertexFormat (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
Vertex box[]{
{ { -0.5,-0.5,-0.5 },{ 0,0,-1 },0,1 },
{ { -0.5,0.5,-0.5 },{ 0,0,-1 },0,0 },
{ { 0.5,0.5,-0.5 },{ 0,0,-1 },1,0 },
{ { 0.5,-0.5,-0.5 },{0,0,-1 },1,1 },
{ { -0.5,-0.5,0.5 },{0,0,1 },0,1 },
{ { -0.5,0.5,0.5 },{ 0,0,1 },0,0 },
{ { 0.5,0.5,0.5 },{ 0,0,1 },1,0 },
{ { 0.5,-0.5,0.5 },{ 0,0,1 },1,1 },
{ { -0.5,-0.5,-0.5 },{ -1,0,0 },0,1 },
{ { -0.5,-0.5,0.5 },{ -1,0,0 },0,0 },
{ { -0.5,0.5,0.5 },{ -1,0,0 },1,0 },
{ { -0.5,0.5,-0.5 },{ -1,0,0 },1,1 },
{ { 0.5,-0.5,-0.5 },{ 1,0,0 },0,1 },
{ { 0.5,-0.5,0.5 },{ 1,0,0 },0,0 },
{ { 0.5,0.5,0.5 },{ 1,0,0 },1,0 },
{ { 0.5,0.5,-0.5 },{ 1,0,0 },1,1 },
{ { -0.5,-0.5,-0.5 },{ 0,-1,0 },0,1 },
{ { -0.5,-0.5,0.5 },{ 0,-1,0 },0,0 },
{ { 0.5,-0.5,0.5 },{ 0,-1,0 },1,0 },
{ { 0.5,-0.5,-0.5 },{ 0,-1,0 },1,1 },
{ { -0.5,0.5,-0.5 },{ 0,1,0 },0,1 },
{ { -0.5,0.5,0.5 },{ 0,1,0 },0,0 },
{ { 0.5,0.5,0.5 },{ 0,1,0 },1,0 },
{ { 0.5,0.5,-0.5 },{ 0,1,0 },1,1 },
};
int index[]{
0,1,2, 0,2,3,
4,5,6, 4,6,7,
8,9,10, 8,10,11,
12,13,14, 12,14,15,
16,17,18, 16,18,19,
20,21,22, 20,22,23
};
//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D(HWND hWnd)
{
// Create the D3D object.
if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
return E_FAIL;
// Set up the structure used to create the D3DDevice. Since we are now
// using more complex geometry, we will create a device with a zbuffer.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// Create the D3DDevice
if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice)))
{
return E_FAIL;
}
// Turn off culling
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// Turn off D3D lighting
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
// Turn on the zbuffer
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: Create the textures and vertex buffers
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
// Use D3DX to create a texture from a file based image
if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, L"9.jpg", &g_pTexture)))
{
// If texture is not in current folder, try parent folder
if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, L"9.jpg", &g_pTexture)))
{
MessageBox(NULL, L"Could not find 9.jpg", L"Texture file not found", MB_OK);
return E_FAIL;
}
}
if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(box),
0, VertexFormat,
D3DPOOL_DEFAULT, &g_pVBGeometry, NULL)))
{
return E_FAIL;
}
if (FAILED(g_pd3dDevice->CreateIndexBuffer(sizeof(index), 0, D3DFMT_INDEX32,
D3DPOOL_DEFAULT, &g_pIBGeometry, 0))) {
return E_FAIL;
}
void *p = NULL;
g_pVBGeometry->Lock(0, 0, &p, 0);
memcpy(p, box, sizeof(box));
g_pVBGeometry->Unlock();
g_pIBGeometry->Lock(0, 0, &p, 0);
memcpy(p, index, sizeof(index));
g_pIBGeometry->Unlock();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if (g_pTexture != NULL)
g_pTexture->Release();
if (g_pVBGeometry != NULL)
g_pVBGeometry->Release();
if (g_pIBGeometry != NULL)
g_pIBGeometry->Release();
if (g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if (g_pD3D != NULL)
g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
// Set up world matrix
D3DXMATRIXA16 matWorld;
D3DXMatrixIdentity(&matWorld);
D3DXMatrixRotationY(&matWorld, timeGetTime() / 1000.0f);
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
D3DXVECTOR3 vEyePt(0.0f, 2.0f, -3.0f);
D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
D3DXMATRIXA16 matProj;
RECT rc;
GetClientRect(GetConsoleWindow(), &rc);
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f*(rc.right-rc.left)/(rc.bottom-rc.top), 1.0f, 100.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}
//-----------------------------------------------------------------------------
// Name: SetupLights()
// Desc: Sets up the lights and materials for the scene.
//-----------------------------------------------------------------------------
VOID SetupLights()
{
// Set up a material. The material here just has the diffuse and ambient
// colors set to yellow. Note that only one material can be used at a time.
D3DMATERIAL9 mtrl;
ZeroMemory(&mtrl, sizeof(D3DMATERIAL9));
mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
mtrl.Specular.r = 0.4f;
mtrl.Specular.g = 0.4f;
mtrl.Specular.b = 0.4f;
mtrl.Specular.a = 0.4f;
g_pd3dDevice->SetMaterial(&mtrl);
// Set up a white, directional light, with an oscillating direction.
// Note that many lights may be active at a time (but each one slows down
// the rendering of our scene). However, here we are just using one. Also,
// we need to set the D3DRS_LIGHTING renderstate to enable lighting
D3DXVECTOR3 vecDir;
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(D3DLIGHT9));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
light.Specular.r = 1.0f;
light.Specular.g = 1.0f;
light.Specular.b = 1.0f;
light.Ambient.r = 0.1f;
light.Ambient.g = 0.1f;
light.Ambient.b = 0.1f;
vecDir = D3DXVECTOR3(cosf(timeGetTime() / 350.0f-60),
-1.0f,
sinf(timeGetTime() / 350.0f - 60));
D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &vecDir);
light.Range = 1000.0f;
g_pd3dDevice->SetLight(0, &light);
g_pd3dDevice->LightEnable(0, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
// Finally, turn on some ambient light.
g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00202020);
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
// Clear the backbuffer and the zbuffer
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
// Begin the scene
if (SUCCEEDED(g_pd3dDevice->BeginScene()))
{
// Setup the world, view, and projection matrices
SetupMatrices();
// Setup our texture. Using textures introduces the texture stage states,
// which govern how textures get blended together (in the case of multiple
// textures) and lighting information. In this case, we are modulating
// (blending) our texture with the diffuse color of the vertices.
g_pd3dDevice->SetTexture(0, g_pTexture);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
g_pd3dDevice->SetStreamSource(0, g_pVBGeometry, 0, sizeof(Vertex));
g_pd3dDevice->SetIndices(g_pIBGeometry);
g_pd3dDevice->SetFVF(VertexFormat);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
// End the scene
g_pd3dDevice->EndScene();
}
// Present the backbuffer contents to the display
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}
int main() {
InitD3D(GetConsoleWindow());
InitGeometry();
SetupLights();
while (true)
{
Render();
}
}