либо пишется для каждой ОС (винда, линукс, яблоко) отдельная реализация основанная на апи системы и потом через макросы делается чтобы например если винда то использовалась виндовая реализация и т.д.
Примерно так, для компиляции - макросы препроцессора, для выполнения - есть разные способы, можно через те же макросы менять значения констант.
либо как то может на ассемлере пишется...
В доступе ниже прикладного уровня главную роль играет не ЯП, а внедрение в ОС, штатными способами (драйвера и т.п.) или с помощью инъекций и т.п., Assembler здесь не главное, это всего лишь очень гибкий и очень неудобный "формат" исполняемого кода и не более.
вручную отрисовка кнопок и прочих элементов интерфейса попиксельно и т.д.
По пикселям никто не рисует, с другой стороны использования стандартных контролов WinAPI (CreateWindow) "в чистом виде" тоже избегают, они недостаточно гибкие и в конце-концов их в нем просто очень мало, лучше реализовать свои "велосипеды", но для отрисовки используется максимально высокоуровневый интерфейс GDI/GDI+/OpenGL/DirectDraw который рисует изображения "зашитые" в библиотеку, и вовсе не по пикселям, а целиком.
А если требуется соответствие графики системной теме оформления, то используется еще и UxTheme - тоже библиотека из WinAPI.
Потому что как тогда объяснить что в том же Qt на всех ОС внешний вид контролов одинаковый?
Разве? В Qt Widgets вроде бы как раз system look and feel.
А вот в Quick (QML) - да, там изображения "зашиты" в саму библиотеку и она их рисует через системное API каждой ОС.