Words of Wisdom Simple Clock, adalah sebuah program jam digital yang secara programming sangatlah sederhana. Program hanya menampilkan jam digital dan sebuah bitmap image berisikan pesan-pesan bijak atau motivator pada layar desktop.

Tujuan dari program ini tak lain adalah untuk memberikan motivasi, bagi saya khususnya, karena saya ini termasuk orang yang moody banget, jadi kalau tidak terus-menerus dimotivasi dan diingatkan, maka mudah sekali konsentrasi dan konsistensi diri ini tergoyahkan, bahkan oleh hal-hal yang sepele.

Dengan adanya program WOW Clock yang sederhana ini, maka dapat sedikit membantu saya untuk tetap fokus dalam belajar dan bekerja. Semoga aplikasi sederhana ini juga bisa bermanfaat bagi Anda.

Program ini saya buat menggunakan Pelles C, sebuah kompiler bahasa C gratis untuk platform Windows. Aplikasi WOW Clock ini saya lengkapi dengan 10 bitmap image yang dapat ditampilkan. Berikut adalah tampilan dari kesepuluh bitmap image tersebut.

Baca juga: https://telinks.wordpress.com/2020/09/25/belajar-pemrograman-bahasa-c-di-windows-pakai-pelles-c-saja/

Program ini lumayan untuk belajar karena melibatkan cukup banyak materi pemrograman, antara lain:

  • timer (SetTimer, WM_TIMER)
  • keyboard input (WM_CHAR, WM_KEYDOWN))
  • mouse input (WM_LBUTTONDOWN, WM_RBUTTONDOWN)
  • bitmap image
  • popup menu
  • grafik (GetDC, SetTextColor, SetBkCoor, DrawText, ReleaseDC)
  • multimedia (PlaySound)

Simak kode program selengkapnya berikut ini.

Kode Program

/*
	Words Of Wisdom Clock (Simple Digital Clock with Bitmap Background)
	Versi 1

	Command:
	- Klik Kiri gambar dan tekan angka 0-9 untuk mengubah gambar
	- Klik Kanan dan Next Image untuk mengubah gambar selanjutnya
	- Klik Kiri dan Prev Image untuk mengubah gambar sebelumnya
	- Tekan tombol ESC untuk keluar
	- Klik Kanan dan Exit untuk keluar
	- Klik Kanan dan About untuk menampilkan About

	Chandra MDE - Teknik Elektro Links
	teknikelektrolinks.com - telinks.wordpress.com - www.usbinov.com
*/

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <wchar.h>

#define ID_ABOUT	4001
#define ID_NEXTIMAGE	4002
#define ID_PREVIMAGE	4003
#define ID_EXIT		4004
#define ID_TIMER	4005

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

char szClassName[ ] = "WOWClock";
HWND hwnd, imagewnd;
HMENU hPopupMenu; 
HDC hdc;

HBITMAP image;

UINT uTimer = 0;
int ImageIndex = 0;
char timeStr[9];
char m1, m2;

static char *imagestr[10] = {"clock.bmp", "clock1.bmp", "clock2.bmp", "clock3.bmp", "clock4.bmp", "clock5.bmp", "clock6.bmp", "clock7.bmp", "clock8.bmp", "clock9.bmp"};

char about[256] = "Words of Wisdom Clock (Simple Bitmap Clock)\nVersi 1\n\nTekan tombol 0-9 atau tombol panah-kanan/kiri\natau Klik Kanan --> Next/Prev Image untuk mengubah gambar.\n\nTeknikChandra MDE\nteknikelektrolinks.com - www.usbinov.com\ntelinks.wordpress.com";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{
	int XX = GetSystemMetrics(SM_CXSCREEN);
	MSG messages; 
	WNDCLASSEX wincl;
	wincl.hInstance = hThisInstance;
	wincl.lpszClassName = szClassName;
	wincl.lpfnWndProc = WindowProcedure;
	wincl.style = CS_DBLCLKS;
	wincl.cbSize = sizeof (WNDCLASSEX);
	wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
	wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
	wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
	wincl.lpszMenuName = NULL; 
	wincl.cbClsExtra = 0;
	wincl.cbWndExtra = 0; 
	wincl.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
	
	if (!RegisterClassEx (&wincl)) return 0;
	hwnd = CreateWindowEx (
		WS_EX_PALETTEWINDOW, 
		szClassName,
    		"TELINKS WOWClock",
    		WS_POPUP | WS_EX_TOPMOST, 
    		XX-175, 1, 102, 121,
    		HWND_DESKTOP,
    		NULL,
    		hThisInstance,
    		NULL
    	);

    imagewnd = CreateWindow("static", "", WS_CHILD | WS_VISIBLE | SS_BITMAP, 0, 0, 102, 121, hwnd, NULL, hThisInstance, NULL);
    image = (HBITMAP)LoadImage(0,"clock.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
    SendMessage(imagewnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)image);

    ShowWindow (hwnd, nFunsterStil);
    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

    return 1;
}

//Fungsi ganti gambar bitmap
void ChangeBitmap(char *bitmap)
{
	if (image!=NULL) DeleteObject(image);
	image = (HBITMAP)LoadImage(0, bitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	if (image)
		SendMessage(imagewnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)image);
	else
		MessageBox(hwnd, "File bitmap tidak ditemukan!", bitmap, MB_ICONERROR);
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT wrc;
	RECT rc;

	switch (message)
	{
		//Inisialisasi Timer ketika window diciptakan
		case WM_CREATE: 
			uTimer = SetTimer(hwnd, ID_TIMER, 1000, NULL);
			if (uTimer==0)
			{
				MessageBox(hwnd, "Timer gagal diciptakan!", "Timer Error", MB_ICONERROR);
				exit(1);
			}
			_strtime( timeStr );
			m1 = timeStr[4];
			m2 = m1;

   			//Create Popup Menu         
			hPopupMenu = CreatePopupMenu();
            InsertMenu(hPopupMenu, 0, MF_BYPOSITION | MF_STRING, ID_ABOUT, "About");
			InsertMenu(hPopupMenu, 1, MF_BYPOSITION | MF_STRING, ID_NEXTIMAGE, "Next Image");
			InsertMenu(hPopupMenu, 2, MF_BYPOSITION | MF_STRING, ID_PREVIMAGE, "Prev Image");
			InsertMenu(hPopupMenu, 3, MF_BYPOSITION | MF_STRING, 0, NULL);
            InsertMenu(hPopupMenu, 4, MF_BYPOSITION | MF_STRING, ID_EXIT, "&Exit");

			break;

		//update tampilan jam digital setiap 1 detik
		case WM_TIMER:
			_strtime( timeStr );
			
			rc.left = 0; rc.top = 101; rc.right = 102; rc.bottom = 121;
			hdc = GetDC(hwnd);
			SetTextColor(hdc, RGB(255, 255, 0));
			SetBkColor(hdc, RGB(0,0,0));
			DrawText(hdc, timeStr, 8, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			ReleaseDC(hwnd, hdc);

			m1 = timeStr[4];
			if (m1<m2) m1 += 10;
			if (m1-m2==2)
			{
				PlaySound("teng.wav", 0, SND_ASYNC);
				if (m1>=10) m1 -= 10;
				m2 = m1;
			}
			break;

		//handler ketika window exit
		case WM_DESTROY:
			KillTimer(hwnd, ID_TIMER);
			DestroyMenu(hPopupMenu);
       		PostQuitMessage (0); //kirim WM_QUIT
       		break;

		//handler ketika Tombol Kiri Mouse ditekan
		case WM_LBUTTONDOWN:
			SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
			break;

		//handler ketika Tombol Kanan Mouse ditekan
		case WM_RBUTTONDOWN:
			GetWindowRect(hwnd, &wrc);
            SetForegroundWindow(hwnd);
            TrackPopupMenu(hPopupMenu, TPM_TOPALIGN | TPM_LEFTALIGN, wrc.left, wrc.bottom, 0, hwnd, NULL);
			break;

		//handler ketika user menekan tombol keyboard ketika window aktif (get focus)
		case WM_CHAR:
			if (wParam==27)
			{
				KillTimer(hwnd, ID_TIMER);
				DestroyMenu(hPopupMenu);
				PostQuitMessage(0);
			}
			else if (wParam>=48 && wParam<=57)
			{
				ImageIndex = wParam-48;
				ChangeBitmap(imagestr[ImageIndex]);
			}
			break;
		case WM_KEYDOWN:
			if (wParam==VK_LEFT)
			{
				if (ImageIndex>0)
					ImageIndex--;
				else
					ImageIndex = 9;
				ChangeBitmap(imagestr[ImageIndex]);
			}
			else if (wParam==VK_RIGHT)
			{
				if (ImageIndex<9)
					ImageIndex++;
				else
					ImageIndex = 0;
				ChangeBitmap(imagestr[ImageIndex]);
			}
			break;

		//handler popup menu
		case WM_COMMAND:
            switch (GET_WM_COMMAND_ID(wParam, lParam))
			{
				case ID_ABOUT:
					MessageBox(hwnd, about, "About", MB_ICONINFORMATION);
					break;

				case ID_NEXTIMAGE:
					if (ImageIndex<9)
						ImageIndex++;
					else
						ImageIndex = 0;
					ChangeBitmap(imagestr[ImageIndex]);
					break;

				case ID_PREVIMAGE:
					if (ImageIndex>0)
						ImageIndex--;
					else
						ImageIndex = 9;
					ChangeBitmap(imagestr[ImageIndex]);
					break;

				case ID_EXIT:
					KillTimer(hwnd, ID_TIMER);
					PostQuitMessage(0);
					break;
			}
			break;

		default:
  			return DefWindowProc (hwnd, message, wParam, lParam);
	}
    return 0;
}

Pembahasan Program

Ketika window aplikasi diciptakan, maka aplikasi akan mencoba mengaktifkan timer dengan fungsi SetTimer. Jika berhasil, maka timer akan berjalan dan mengirimkan MESSAGE WM_TIMER setiap 1000 ms atau setiap 1 detik. Selain mengaktifkan timer, aplikasi juga melakukan inisialisasi terhadap popup menu.

//Inisialisasi Timer ketika window diciptakan
case WM_CREATE:
  uTimer = SetTimer(hwnd, ID_TIMER, 1000, NULL);
  if (uTimer==0)
  {
    MessageBox(hwnd, "Timer gagal diciptakan!", "Timer Error", MB_ICONERROR);
    exit(1);
  }
  _strtime( timeStr );
  m2 = timeStr[4];
  
  //Create Popup Menu
  hPopupMenu = CreatePopupMenu();
  InsertMenu(hPopupMenu, 0, MF_BYPOSITION | MF_STRING, ID_ABOUT, "About");
  InsertMenu(hPopupMenu, 1, MF_BYPOSITION | MF_STRING, ID_NEXTIMAGE, "Next Image");
  InsertMenu(hPopupMenu, 2, MF_BYPOSITION | MF_STRING, ID_PREVIMAGE, "Prev Image");
  InsertMenu(hPopupMenu, 3, MF_BYPOSITION | MF_STRING, 0, NULL);
  InsertMenu(hPopupMenu, 4, MF_BYPOSITION | MF_STRING, ID_EXIT, "&Exit");
  break;

Setiap kali WM_TIMER muncul, maka aplikasi akan melakukan update tampilan digital clock. Dan jika terjadi perubahan menit, maka aplikasi akan memainkan file WAVE “teng.wav”.

//update tampilan jam digital setiap 1 detik
case WM_TIMER:
  _strtime( timeStr );

  rc.left = 0; rc.top = 101; rc.right = 102; rc.bottom = 121;
  hdc = GetDC(hwnd);
  SetTextColor(hdc, RGB(255, 255, 0));
  SetBkColor(hdc, RGB(0,0,0));
  DrawText(hdc, timeStr, 8, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  ReleaseDC(hwnd, hdc);

  m1 = timeStr[4];
  if (m1!=m2)
  {
    PlaySound("teng.wav", 0, SND_ASYNC);
    m2 = m1;
  }
  break;

Untuk mengganti gambar backround dapat dilakukan dengan cara sbb:

  • menekan tombol 0 – tombol 9 pada keyboard
  • menekan tombol panah-kiri atau panah-kanan pada keyboard
  • klik-kanan mouse dan pilih menu Next Image atau Prev Image

Untuk menempatkan window aplikasi pada layar desktop sesuai keinginan, Anda bisa melakukan drag pada window aplikasi WOW Clock. Agar clock bisa di drag, maka kita perlu mengalihkan MESSAGE WM_LBUTTONDOWN kepada HTCAPTION menjadi MESSAGE WM_NCLBUTTONDOWN.

    //handler ketika Tombol Kiri Mouse ditekan
    case WM_LBUTTONDOWN:
        SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
        break;

Pada popup menu juga terdapat menu About yang akan menampilkan form About seperti tampilan berikut ini:

Dan untuk menutup aplikasi, bisa menggunakan keyboard tombol ESC atau mouse klik-kanan –> Exit.

Download Aplikasi

Anda dapat mengunduh file aplikasi Words Of Wisdom Clock secara gratis melalui link berikut ini:

Download WordsOfWisdomClock.rar

Pelatihan Privat Pemrograman dan Pembuatan Program C

Kami melayani Pelatihan Privat Pemrograman C tingkat dasar dan juga melayani pembuatan program C untuk platform Windows, Linux dan Arduino. Selain C, kami juga melayani pelatihan dan pembuatan program menggunakan Lazarus/Freepascal.

Hubungi kami melalui WA 0882-3560-7047.

Selamat belajar. Selamat berkarya.